我有一个像这样的SQL查询:
SELECT t1.key, t1.value
FROM table1 AS t1, table2 AS t2
WHERE t1.pID IN (45, 67, 88, 32) AND t2.id = t1.id;
这似乎返回t1.pId IN (45, 67, 88, 32)
的所有行,但它不应该因为t2.id应该进一步减少行结果,但似乎不是这样做。
我需要减少通过t2.id返回的行,但是如果在对t1.pId values数组进行排序后找不到t2.id,则应返回空结果。
EDITED
表,尝试选择t1
列,而不是t2
,抱歉。但只有满足两个条件,并且仅在第二个条件为真后才返回结果行。此外,现在修复表格,使其正确。
答案 0 :(得分:1)
您的查询返回符合指定条件的每一行。也就是说,它仅检查单个行是否满足谓词,并返回所执行的行,而不管任何不行的行。
如果我理解你要问的是什么(而且我并不完全确定我这么做),你说你想要回复一个空集"当某些行满足t1.id上的谓词时,但t1中至少有一行在t2中没有匹配的行。
检查是否有任何行没有"匹配"在t2中,我们可以使用反连接模式(还有其他方法......
SELECT SUM(1) AS t1_rows_not_matched
FROM table1 t1
LEFT
JOIN table2 t2
ON t2.id = t1.id
WHERE t1.pID IN (45, 67, 88, 32)
AND t2.id IS NULL
将其合并到您的查询中,您可以将其用作内联视图,并包含一个谓词来检查不匹配的行数,例如:
SELECT d.key
, d.value
FROM ( SELECT SUM(1) AS cnt_rows_not_matched
FROM table1 t1
LEFT
JOIN table2 t2
ON t2.id = t1.id
WHERE t1.pID IN (45, 67, 88, 32)
AND t2.id IS NULL
) c
CROSS
JOIN table1 d
WHERE d.pID IN (45, 67, 88, 32)
AND c.cnt_rows_not_matched = 0
这可能无法解答您提出的问题,但目前尚不清楚您的要求。
单独检查每一行。如果a满足谓词,则返回。只有在没有匹配的行时,您发布的查询才会返回空集。
您可能希望检查至少有一行与列表中包含的每个pID
值相匹配。也就是说,例如,如果没有pID值为32
的行,那么您希望查询返回一个空集,而不是符合条件的行集。
SELECT d.key
, d.value
FROM ( SELECT SUM(1) AS cnt_rows_not_matched
FROM table1 t1
LEFT
JOIN table2 t2
ON t2.id = t1.id
WHERE t1.pID IN (45, 67, 88, 32)
AND t2.id IS NULL
) c
CROSS
JOIN ( SELECT COUNT(DISTINCT f.pID) AS cnt_pid
FROM table1 f
WHERE f.pID IN (45, 67, 88, 32)
) p
CROSS
JOIN table1 d
WHERE d.pID IN (45, 67, 88, 32)
AND c.cnt_rows_not_matched = 0
AND p.cnt_pid = 4
答案 1 :(得分:0)
我不确定加入表的逗号语法是否会导致MySQL做一些你不期望的事情,但是如果你重写它以使用一个明确的JOIN,那么我认为你会发现它更清楚你的地方条件是和JOIN如何发生。这是一个建议:
SELECT t2.key, t2.value
FROM table1 AS t1
LEFT OUTER JOIN table2 AS t2 ON t1.id = t2.id
WHERE t1.id IN (45, 67, 88, 32)
AND t2.id IS NOT NULL
这里的想法是你明确加入表t2,并声明它应该如何加入。
然后,通过在t2.id
中删除所有带有NULL的行,将行减少到仅成功连接的行。如果在t2.id
t1.id = t2.id
将为null