2012-01-23 94 views
3

我有兩個表: PPC(主/從由列ID接合)SQL子查詢替代相交

Table P: 
Id integer 
Name varchar(12) 

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

我想獲得與P滿足以下的聯立條件的所有名稱:

  • 有一臺PC與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)向您展示瞭如何一般性地用JOIN重寫INTERSECT查詢。具體來說,請參閱Vinko Vrsalovic的解決方案。 – 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

酷,我會upvote你取消誰是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子句需要爲

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 - OP要求替代品。這是一個通過表。 –

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 
         );