SQL 联结查询 - 如何获得精确匹配

SQL Junction Query - How To Get Exact Match

我希望这个问题的答案与 DBMS 无关,但如果相关,我正在使用 Access SQL。

请注意,这是我正在尝试做的事情的简化版本。

现在,假设我有以下三个 table。

我的主要水果table(tblFruits):

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

table 到 link 多个标签到 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           ║
╚════════════════╩═════════╩═════════════╝    

最后是一个标签 table 来标记我的水果 (tblTag):

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

感谢This Blog Post让我偷懒)

这基本上是说:

  1. 苹果是(红色、闪亮、美味、美味)
  2. 橘子是(Orange)
  3. 葡萄柚是(橙色,糟糕)

现在说我想要 select 那些带有标签 '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

这会 return 结果同时包含橙子和葡萄柚,但我只想要橙子。

我这样做 SQL 声明的原因是不同类型的水果可能具有相同的名称但不同的标签或不同的水果可能除了一个相同的标签外都具有相同的标签。

编辑:

SQLFiddle as requested.

您走在正确的轨道上,但您需要在 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;

请注意 "right" 表达条件的方式是使用 CASE 而不是 IIF()。此外,Access 通常需要在联接周围使用很多丑陋的括号,我也将其省略。