SQL显示其他类别中不存在的项目

时间:2014-07-16 20:29:57

标签: sql sql-server tsql sql-server-2012

我有一个Tier,Category和Items的表。对于Tier = 2,每个类别应具有相同的项目数。我想显示每个类别中缺少的项目。

以下是一个示例表:

IF OBJECT_ID('tempdb..#Items') IS NOT NULL DROP TABLE #Items
CREATE TABLE #Items (
    Tier        int,
    Category    nvarchar(25),
    Item        nvarchar(25)
)

INSERT INTO #Items
SELECT '2', 'CategoryA',    'Item1'
UNION ALL
SELECT '2', 'CategoryA',    'Item2'
UNION ALL
SELECT '2', 'CategoryA',    'Item3'
UNION ALL
SELECT '2', 'CategoryB',    'Item1'
UNION ALL
SELECT '2', 'CategoryB',    'Item3'
UNION ALL
SELECT '2', 'CategoryC',    'Item1'
UNION ALL
SELECT '2', 'CategoryC',    'Item2'
UNION ALL
SELECT '2', 'CategoryC',    'Item3'
UNION ALL
SELECT '2', 'CategoryC',    'Item4'

SELECT
    Tier,
    Category,
    Item
FROM #Items
ORDER BY Tier, Category, Item

Tier    Category    Item
2   CategoryA   Item1
2   CategoryA   Item2
2   CategoryA   Item3
2   CategoryB   Item1
2   CategoryB   Item3
2   CategoryC   Item1
2   CategoryC   Item2
2   CategoryC   Item3
2   CategoryC   Item4

如果我显示每个类别中的项目数:

SELECT
    Tier,
    Category,
    COUNT(Item) as ItemCount
FROM #Items
GROUP BY Tier, Category

他们应该都有相同的4项:

Tier    Category    ItemCount
2   CategoryA   3
2   CategoryB   2
2   CategoryC   4

我想显示每个类别中缺少的项目列表。这可能有效,但显然是笨拙的,只是为了呈现我希望看到它的数据。

SELECT DISTINCT
    Tier,
    'CategoryA' as [Category],
    Item
FROM #Items i
WHERE Item NOT IN (SELECT Item from #Items WHERE Category = 'CategoryA')
UNION ALL
SELECT DISTINCT
    Tier,
    'CategoryB' as [Category],
    Item
FROM #Items i
WHERE Item NOT IN (SELECT Item from #Items WHERE Category = 'CategoryB')
UNION ALL
SELECT DISTINCT
    Tier,
    'CategoryC' as [Category],
    Item
FROM #Items i
WHERE Item NOT IN (SELECT Item from #Items WHERE Category = 'CategoryC')

并显示结果:

Tier    Category    Item
2   CategoryA   Item4
2   CategoryB   Item2
2   CategoryB   Item4

2 个答案:

答案 0 :(得分:5)

您可以使用项目的笛卡尔积,然后拉出源表中不存在的项:

SELECT DISTINCT
    i1.Tier,
    i1.[Category],
    i2.Item
FROM Items i1, Items i2
WHERE i2.Item NOT IN (SELECT Item from Items WHERE Category = i1.Category)

结果:

TIER    CATEGORY    ITEM
----    --------    -----
2       CategoryA   Item4
2       CategoryB   Item2
2       CategoryB   Item4

你可以test the query here

答案 1 :(得分:0)

我会通过交叉连接执行此操作,然后将其连接回自身:

select
     _Categories.category
    ,_Items.item
from(
  select distinct
      category
  from Items
) _Categories
cross join (
  select distinct
      item
  from items
) _Items
left join Items _ActualItems
  on _ActualItems.category = _Categories.category
  and _ActualItems.item = _Items.item
where _ActualItems.item is null

以下是SQL Fiddle Example