2012-01-23 3 views
3

У меня есть две таблицы: P и PC (мастер/подробно присоединился колонке Id)SQL подзапросов альтернатива пересекаться

Table P: 
Id integer 
Name varchar(12) 

Table PC: 
Id integer 
Code varchar(12) 
Val number 

Я хочу, чтобы получить все имена из P, которые удовлетворяют следующим одновременные условиям:

  • есть компьютер с PC.Code='A' и Val>100

  • есть другой компьютер с PC.Code='B' и Val>80

В целом, я заинтересован только в тех P.Name где детали соответствуют обоим условиям. Есть ли способ выбрать, не прибегая к INTERSECT?

Запрос ПЕРЕСЕЧЕНИЕ является:

Select P.Name 
    from P, PC 
where P.Id=PC.Id 
    and PC.Code='A' and Val>100 
INTERSECT 
Select P.Name 
    from P, PC 
where P.Id=PC.Id 
    and PC.Code='B' and Val>80 

(Интерес для проверки производительности, а также, чтобы запрос будет работать в Access)

+0

[Статья] (http://stackoverflow.com/questions/2302873/sql-syntax-error-with-intersect) показывает вам, как в общем случае переписывать запросы INTERSECT с помощью JOIN. В частности, см. Решение Винко Врсаловича. – mwigdahl

ответ

1

Не знаю, как производительность .. попробовать ..

SELECT P.Name 
    FROM P 
    INNER JOIN PC AS a ON P.Id=a.Id and a.Cod='A' and a.Val>100 
    INNER JOIN PC AS b ON P.Id=b.Id and a.Cod='B' and a.Val>80 
0
SELECT P.Name 
    FROM P 
    JOIN PC AS P1 ON P.Id = P1.Id AND P1.Cod = 'A' AND P1.Val > 100 
    JOIN PC AS P2 ON P.Id = P2.Id AND P2.Cod = 'B' AND P2.Val > 80 

Использование таблицы псевдонимов P1 и P2 позволяет сделать 3-стороннее соединение. Тем не менее, это не совсем самосознание; не в этот раз.

0
Select p.Name 
from P p 
inner join PC pc1 on p.Id = pc1.Id and pc1.Cod = 'A' and pc1.Val > 100 
inner join PC pc2 on p.Id = pc2.Id and pc2.Cod = 'B' and pc2.Val > 80 
+1

Нет, это не сработает, поскольку PC.Cod не может одновременно быть как «A», так и «B». Вам нужно второе соединение. – mwigdahl

+0

@mwigdahl, вы правы, я исправил свой запрос. –

+0

Прохладный, я подниму вас на то, чтобы отменить кого бы то ни было, что было downvoted ... :) – mwigdahl

0
Select P.Name 
    from P, PC 
where P.Id=PC.Id 
    and PC.Cod='A' and Val>100 
    and exists (Select 1 From PC Where Id = P.Id and Cod = 'B' and Val > 80) 
+0

Вы проверили это в Access? Я спрашиваю, что 'Val' и' Name' являются зарезервированными словами. – onedaywhen

0

Не было на самом деле использовать это, но альтернатива ...

SELECT P.Name 
FROM P 
     JOIN PC 
     ON P.Id = PC.Id 
WHERE PC.Cod IN ('A', 'B') 
     AND Val > 80 
GROUP BY P.Id, 
      P.Name 
HAVING MAX(CASE WHEN PC.Cod='A' and Val>100 THEN 1 END) = 1 
AND MAX(CASE WHEN PC.Cod='B' and Val>80 THEN 1 END) = 1 

Или для Microsoft Access должно быть должно быть

HAVING MAX(IIf(PC.Cod='A' and Val>100, 1, 0)) = 1 
AND MAX(IIf(PC.Cod='B' and Val>80, 1, 0)) = 1 
+0

Не проголосовать, но невероятно исказить. Это сработает, но вряд ли будет прямой перевод требований. –

+0

@JonathanLeffler - ОП запросил альтернативы. Это проходит через таблицу. –

1

Вот альтернативный подход, который является реляционно эквивалентным (т. устраняющие повторяющиеся строки):

SELECT P.Name 
    FROM P 
WHERE EXISTS (
       SELECT * 
       FROM PC 
       WHERE P.Id = PC.Id 
         AND PC.Code ='A' 
         AND PC.Val > 100 
      ) 
     AND EXISTS (
        SELECT * 
        FROM PC 
        WHERE P.Id = PC.Id 
         AND PC.Code ='B' 
         AND PC.Val > 80 
       ); 

Вот несколько альтернатив, которые семантически эквивалентны (в том, что они могут возвращать повторяющиеся строки):

SELECT P.Name 
    FROM P, PC 
WHERE P.Id = PC.Id 
     AND PC.Code ='A' 
     AND PC.Val > 100 
     AND P.Name IN (
         SELECT P1.Name 
         FROM P AS P1, PC AS PC1 
         WHERE P1.Id = PC1.Id 
         AND PC1.Code = 'B' 
          AND PC1.Val > 80 
        ); 
SELECT P.Name 
    FROM P, PC 
WHERE P.Id = PC.Id 
     AND PC.Code ='A' 
     AND PC.Val > 100 
     AND P.Name = ANY (
         SELECT P1.Name 
          FROM P AS P1, PC AS PC1 
          WHERE P1.Id = PC1.Id 
          AND PC1.Code = 'B' 
           AND PC1.Val > 80 
         ); 

 Смежные вопросы

  • Нет связанных вопросов^_^