Подзапрос SQL со сложными критериями - PullRequest
2 голосов
/ 02 февраля 2012

У меня есть такая таблица:

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 и (accountId = 2 или 5)) а также (LayerNo = 2 и (accountId = 3 или 6))

И результирующим набором будет строка № 1,2,3,4. Как я мог написать запрос, чтобы получить результат? Моя база данных SQL Server 2008 R2 заранее спасибо Нима

Ответы [ 7 ]

5 голосов
/ 02 февраля 2012
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 ) )  
3 голосов
/ 02 февраля 2012

Одним из подходов является обеспечение того, чтобы каждый 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
    )

Однако это может быть проблемой, если у вас может быть несколько записей, где 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 ) 

Тем не менее ИНТЕРСЕКТ Мартина подход, вероятно, лучший

0 голосов
/ 04 февраля 2012

Это пересечение пусто.Если вы берете значения, где LayerNo = 1 и LayerNo = 2, и пересекаете их, их пересечение будет пустым, потому что эти события являются взаимоисключающими.Я считаю, что эта ошибка возникла из-за того, как вопрос был поставлен изначально.Я могу ошибаться, но предикат должен был быть (LayerNo = 1 и (accountId = 2 или 5)) OR (LayerNo = 2 и (accountId = 3 или 6)) Заменить AND на ИЛИЕсли предикат был задан правильно, то пересечение корректно, но всегда будет пустым.

0 голосов
/ 02 февраля 2012
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 голосов
/ 02 февраля 2012
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 голосов
/ 02 февраля 2012

Вы имеете в виду:

SELECT 
   TransId,  
   LayerNo,  
   AccountId
FROM Table
WHERE (LayerNo = 1 AND AccountId IN (2, 5)) OR 
      (LayerNo = 2 AND AccountId IN (3, 7))
0 голосов
/ 02 февраля 2012
SELECT  *
  FROM  table
 WHERE  (LayerNo = 1 AND (AccountID = 2 OR AccountID = 5))
   OR   (LayerNo = 2 AND (AccountID = 3 OR AccountID = 6))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...