Select 将 return 一条记录基于多条记录的语句

Select statement that will return one record based on multiple records

看过类似的题,但不完全一样。我有一个带有多个 ID 的 table,我想做一个适合所有 PID 的 select 语句和 return ID once.

+----+-----+-----+-------+
| ID | PID | DET | DETOP |
+----+-----+-----+-------+
|  1 | 123 | TR  | EQ    |
|  1 | 234 | US  | EQ    |
|  1 | 536 | L   | EQ    |
|  2 | 123 | TR  | EQ    |
|  2 | 234 | US  | EQ    |
|  2 | 536 | D   | EQ    |
+----+-----+-----+-------+

换句话说,如果 123=TR 且 234=US 且 536=L(希望这是有道理的)return 1 而不是 1,1,1。

我做不到

SELECT ID 
FROM MYTABLE 
WHERE PID = 123 
  AND DET = 'TR' 
  AND PID = 234 
  AND DET = 'US' 
  AND PID = 536 
  AND DET = 'L'

因为那样只会 return 零结果。最好的方法是什么?

我想你想要一个 HAVING?

SELECT ID
FROM dbo.YourTable
GROUP BY ID
HAVING COUNT(CASE WHEN PID = 123 AND DET = 'TR' THEN 1 END) > 0
   AND COUNT(CASE WHEN PID = 243 AND DET = 'US' THEN 1 END) > 0
   AND COUNT(CASE WHEN PID = 536 AND DET = 'L' THEN 1 END) > 0;

您可以使用聚合和 having。假设没有重复的 (id, pid, det),您可以将其表述为:

select id
from mytable
where 
    (pid = 123 and det = 'TR') 
    or (pid = 234 and det = 'US') 
    or (pid = 536 and det = 'L')
group by id
having count(*) = 3

这是关系划分的经典案例。解决方案是:

CREATE TABLE MYTABLE (ID  INT,
                      PID INT , 
                      DET CHAR(3),
                      DETOP  CHAR(2),
                      PRIMARY KEY (ID, PID));
GO
INSERT INTO MYTABLE VALUES
(1,     123,   'TR',     'EQ'),
(1,     234,   'US',     'EQ'),
(1,     536,   'L ',     'EQ'),
(2,     123,   'TR',     'EQ'),
(2,     234,   'US',     'EQ'),
(2,     536,   'D ',     'EQ');

为了数据测试。

查询解决:

WITH 
DATASET AS
(SELECT * 
 FROM (VALUES (123, 'TR'), 
              (234, 'US'), 
              (536, 'L')) 
       T(PID, DET))
SELECT M.ID
FROM   DATASET AS D
       JOIN MYTABLE AS M
          ON D.PID = M.PID AND D.DET = M.DET
GROUP  BY M.ID
HAVING COUNT(*) = (SELECT COUNT(DISTINCT PID) 
                   FROM   DATASET)