SQL带有连接表的子句 - 或者有效,但是不能

时间:2013-08-08 21:02:02

标签: sql tsql

假设我有两个表定义如下:

Items
-----
Id (Primary Key)
ItemName


ItemsTags
-----
ItemId (Primary Key)
TagName (Primary Key)

并填写以下数据:

Items
-----
1, Item1
2, Item2
3, Item3

ItemsTags
--------
1, Tag1
1, Tag2
1, Tag3
2, Tag3
3, Tag4
3, Tag5

假设我想搜索分配了EITHER Tag1或Tag3的项目,则以下查询有效:

SELECT DISTINCT Items.Id
FROM Items INNER JOIN ItemsTags
    ON Items.Id = ItemsTags.ItemId
WHERE ItemsTags.TagName = 'Tag1' OR ItemsTags.TagName = 'Tag3'

导致返回1和。

但是,如何修改该查询以便为我提供具有BOTH Tag1和Tag3的项目?显然,以下查询不起作用,因为对于任何给定的行,TagName不能同时为两个不同的值。

SELECT DISTINCT Items.Id
FROM Items INNER JOIN ItemsTags
     ON Items.Id = ItemsTags.ItemId
WHERE ItemsTags.TagName = 'Tag1' AND ItemsTags.TagName = 'Tag3'

什么是正确的查询?在我的例子中,我希望只返回第1项。

5 个答案:

答案 0 :(得分:2)

试试这个:

SELECT DISTINCT i.Id
FROM Items i
INNER JOIN ItemsTags it1 ON i.Id = it1.ItemId and it1.TagName='Tag1'
INNER JOIN ItemsTags it3 ON i.Id = it3.ItemId and it3.TagName='Tag3'

Here是一个SQL小提琴。

答案 1 :(得分:1)

使用exists子句:

SELECT 
    Items.Id 
FROM 
    Items  
Where 
    Exists (
        Select top 1 1 
        FROM 
            ItemsTags 
        WHERE 
            ItemsTags.ItemId = Items.Id    
            and (ItemsTags.TagName= 'Tag1') 
    )
 AND 
 Exists (
        Select top 1 1 
        FROM 
            ItemsTags 
        WHERE 
            ItemsTags.ItemId = Items.Id    
            and (ItemsTags.TagName= 'Tag3') 
    )

答案 2 :(得分:1)

另一种方法:

SELECT DISTINCT Items.Id FROM Items  
WHERE 
     Items.Id IN (SELECT ItemId FROM ItemsTags WHERE TagName = 'Tag1') AND
     Items.Id IN (SELECT ItemId FROM ItemsTags WHERE TagName = 'Tag3')

答案 3 :(得分:1)

你也可以这样做。

SELECT items.ID
FROM items
INNER JOIN ItemsTags ON
  Items.Id = ItemsTags.ItemId
WHERE ItemsTags.TagName IN ('Tag1','Tag3')
GROUP BY
 items.ID
HAVING COUNT(*) = 2

答案 4 :(得分:0)

这样做的另一种可行方式只是为了说明在sql中执行任何操作的无数方法,这次采用了与其他方法截然不同的方法。

SELECT i.Id
FROM Items i
JOIN (
  SELECT ItemId
  FROM ItemsTags
  WHERE TagName IN ('Tag1', 'Tag3')
  GROUP BY ItemId
  HAVING COUNT(*) > 1
) t ON t.ItemId = i.Id

SqlFiddle