SQL连接查询 - 如何获得完全匹配

时间:2015-03-03 20:49:25

标签: sql ms-access select junction-table

我希望这个问题的答案是DBMS不可知的,但如果它是相关的,我使用的是Access SQL。

请注意,这是我想要做的简化版本。

现在,请考虑我有以下三个表。

我的主要水果表(tblFruits):

╔═════════╦═══════════╦
║ fruitID ║ fruitName ║ 
╠═════════╬═══════════╬
║ 1       ║ Apple     ║ 
║ 2       ║ Orange    ║ 
║ 3       ║ Grapefruit║ 
╚═════════╩═══════════╩

将许多标签链接到1个水果(tblFruitTagJunc)的联结表:

╔════════════════╦═════════╦═════════════╗
║ fruitTagJuncID ║ fruitID ║ tagID       ║
╠════════════════╬═════════╬═════════════╣
║ 1              ║ 1       ║ 1           ║
║ 2              ║ 1       ║ 2           ║
║ 3              ║ 1       ║ 4           ║
║ 4              ║ 1       ║ 5           ║
║ 5              ║ 2       ║ 3           ║
║ 6              ║ 3       ║ 3           ║
║ 7              ║ 3       ║ 6           ║
╚════════════════╩═════════╩═════════════╝    

最后是一个用于标记我的水果的标签表(tblTag):

 ╔═════════╦═══════════╗
 ║ tagID   ║  tag      ║
 ╠═════════╬═══════════╣
 ║ 1       ║ Tasty     ║
 ║ 2       ║ Red       ║
 ║ 3       ║ Orange    ║
 ║ 4       ║ Shiny     ║
 ║ 5       ║ Delicious ║
 ║ 6       ║ Awful     ║
 ╚═════════╩═══════════╝

感谢This Blog Post让我变懒“

这基本上说明了:

  1. 苹果(红色,闪亮,美味,美味)
  2. 橘子是(橙色)
  3. 葡萄柚是(橙色,可怕)
  4. 现在说我要选择那些标有'Orange'而没有其他水果的水果。根据提供的数据,只有fruitName = 'Orange'的数据。我目前正在这样做:

    SELECT F.fruitName 
    FROM tblFruits F
    INNER JOIN tblFruitTagJunc AS FTJ on F.fruitID = FTJ.fruitID
    INNER JOIN tbltag as T ON FTJ.tagID = T.tagID
    WHERE T.tag in('Orange') 
    GROUP BY F.fruitName
    HAVING count(T.tag) = 1
    

    结果会返回Orange和Grapfruit,但我只想要Orange。

    我这样做SQL语句的原因是不同类型的水果可能具有相同的名称但不同的标签或不同的水果可能只有一个相同的标签。

    编辑:

    SQLFiddle as requested

1 个答案:

答案 0 :(得分:2)

您走在正确的轨道上,但您需要having子句中的条件聚合,而不是where子句。当您使用where时,您永远不会看到其他标签。

所以:

SELECT F.fruitName 
FROM tblFruits as F INNER JOIN
     tblFruitTagJunc AS FTJ
     on F.fruitID = FTJ.fruitID INNER JOIN
     tbltag as T
     ON FTJ.tagID = T.tagID
GROUP BY F.fruitName
HAVING SUM(iif(t.tag in ('Orange'), 1, 0) > 0 AND
       COUNT(t.tag) = 1;

请注意"对"表达条件的方式是使用CASE而不是IIF()。访问通常需要在连接周围使用大量丑陋的括号,我也将其遗漏。