2012-02-01 86 views
2

我有这样一个表:SQL子查询与复杂的标准

TransId. LayerNo. AccountId. 
100.  1.  2.   
100.  2.  3.   
120.  1.  5.   
120.  2.  6.  
120.  3.  12.  
70.  1.  2. 

我想找到TRANSID(s)的结合: (LayerNo = 1和(帐户= 2或5)) 和 (LayerNo = 2和(accountId = 3或6))

而结果集是行号1,2,3,4。 我如何写查询来获得结果? 我的数据库是SQL Server 2008 R2的 预先感谢 尼玛

+1

是否有和以上的?无论其他值如何,都无法使LayerNo = 1和LayerNo = 2。 – 2012-02-01 21:28:44

+0

LayerNo如何成为1和2?你的意思是“还是LayerNo = 2”? – 2012-02-01 21:29:58

+0

基于期望的结果集,他正在寻找既满足**条件又满足**条件的TransID,因此对LayerNo 1 AND 2与1 OR 2的混淆 – nybbler 2012-02-01 21:38:34

回答

5
SELECT TransId 
FROM your_table 
WHERE (layerno = 1 
     AND accountid IN (2, 5)) 
INTERSECT 
SELECT TransId 
FROM your_table 
WHERE (layerno = 2 
     AND accountid IN (3, 6)) 
+0

+1我总是忘记INTERSECT。非常好。 – 2012-02-01 21:49:13

+0

+1 INTERSECT的良好通话。 – nybbler 2012-02-01 22:09:45

+0

是的,这是greate :) – nima 2012-02-02 06:58:36

3

一种方法是确保每个TRANSID必须有两个记录满足你列出的条件。

SELECT * FROM 
TABLE 
WHERE TransID IN( 
    SELECT TransId 
    FROM table 
    WHERE (layerno = 1 
      AND accountid IN (2, 5) ) 
      OR (layerno = 2 
       AND accountid IN(3, 6) ) 
    GROUP BY 
     TransId 
    HAVING Count(*) = 2 
    ) 

然而,这可能是一个问题,如果你可以有multple记录,其中layerno = 1,所以,你可以使用自联接来代替,以保证标准。

SELECT DISTINCT a.transid 
FROM table a 
     INNER JOIN table b 
     ON a.transid = b.transid 
     INNER JOIN table c 
     ON a.transid = c.transid 
WHERE b.layerno = 1 
     AND accountid IN (2, 5) 
     AND c.layerno = 2 
     AND accountid IN (3, 6) 

也就是说Martin's INTERSECT做法可能是最好的

+1

这将包括结果集中的第6行,即不想要 – nybbler 2012-02-01 21:39:06

+0

@nybbler。感谢您指出了这一点。固定 – 2012-02-01 21:42:33

+0

你的答案也做这项工作,但正如你所说康莱德的解决方案更容易和更多我有层面检查,更多的联合应该介入,我认为这将是一个性能问题。我对吗? – nima 2012-02-02 07:12:54

-1
SELECT * 
    FROM table 
WHERE (LayerNo = 1 AND (AccountID = 2 OR AccountID = 5)) 
    OR (LayerNo = 2 AND (AccountID = 3 OR AccountID = 6)) 
+0

他只需要有符合两个条件的行的transids。这只会检查单行。 – JNK 2012-02-01 21:50:21

0

你的意思是:

SELECT 
    TransId, 
    LayerNo, 
    AccountId 
FROM Table 
WHERE (LayerNo = 1 AND AccountId IN (2, 5)) OR 
     (LayerNo = 2 AND AccountId IN (3, 7)) 
0
create table #temp 

(rowId Int Identity(1,1), transId int) 

INSERT INTO #temp(transId) 
select TransId 
from TableName 
where (layerNo = 1 and accountID IN (2, 5)) 
OR (layerNo = 2 and accountId IN (3, 6)) 
select * from #temp 
0
SELECT 
    base.TransId, 
    base.LayerNo, 
    base.AccountId 
FROM TableX AS base 
    JOIN TableX AS a 
    ON a.TransId = base.TransId 
    AND a.LayerNo = 1 AND a.AccountId IN (2, 5) 
    JOIN TableX AS b 
    ON b.TransId = base.TransId 
    AND b.LayerNo = 2 AND b.AccountId IN (3, 7) 
WHERE (base.LayerNo = 1 AND base.AccountId IN (2, 5)) 
    OR (base.LayerNo = 2 AND base.AccountId IN (3, 7)) 
0

这个交点是空的。如果将LayerNo = 1和LayerNo = 2的值与相交,则它们的交集为空,因为这些事件是互斥的。我相信这个错误来自于最初陈述问题的方式。我可能是错的,但谓词应该是 (LayerNo = 1和(accountId = 2或5))OR(LayerNo = 2和(accountId = 3或6)) 用AND替换AND。如果谓词正确表示,则相交是正确的,但始终为空。