2014-06-16 63 views
0

我有一个SQL查询,像这样:MySQL必须匹配两个表中的两列......否则返回空结果?

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值数组排序后找不到t2.id,它应该返回一个空结果。

EDITED 表,试图选择t1列,不t2,对不起。但是只有满足这两个条件,并且只有在第二个条件为真后才返回结果行。此外,现在修复表格,以便它是正确的。

+1

如果你加入2个表之间的公用密钥的数据是什么? –

+0

2之间没有共同的关键...对不起 –

+0

't2.id = t1.pID'暗示这是两个表之间的公共关键。 –

回答

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将为空如果没有匹配的t2行,当加入t1.id = t2.id

+0

已更新的问题,对不起,不完全正确...请看看。谢谢:) –

+0

我不知道我是否理解你的编辑,但它看起来像你只是改变了一些列名和/或想选择不同的列。我更新了SQL以反映我注意到的更改,但这只是更改列名称的问题。同样的技术应该仍然有效。 – Josh

1

您的查询返回符合指定条件的每一行。也就是说,它只检查单个行是否满足谓词,并返回所做的行,而不管没有行的行。

如果我明白你在问什么(我不完全确定我是这么做的),你说你想在某些行满足t1.id上的谓词时返回一个“空集”,但至少有一个在t2中没有匹配行的t1中的行。

要检查是否有行没有在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 

这可能不是回答你问的问题,但它不是清楚你在问什么。


每行都单独检查。如果满足谓词,它将被返回。只有在没有匹配的行时,您发布的查询才会返回空集。

您可能希望检查是否至少有一行匹配列表中包含的每个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 

+0

我想返回符合'WHERE'语句的所有行。否则,不要返回它们,而是返回一个空的结果。这有助于更清楚吗?并且谢谢btw。 –

+0

再次感谢,但我不认为你在这里跟着我。我只想返回两个WHERE条件都为真的行......就像我通常在table2上做一个INNER JOIN一样,如果table2的ON语句不是真的,它应该去掉左表值。这正是我想要做的,但不要认为'INNER JOIN'会在这里工作......除非我错了? –

+0

声明中只有一个WHERE子句,而不是两个。 WHERE子句中有两个_predicates_。布尔AND运算符指定一行必须满足_both_谓词才能返回。这就是你原来的陈述所做的。使用内部连接,谓词是出现在WHERE子句还是ON子句中并不重要。 (老式的逗号连接操作符,就像在你的查询中一样,是一个连接操作,缺少示例数据和期望的结果(以及与你发布的查询的输出有什么不同,我无法帮到你) – spencer7593

相关问题