[英]SQL Server- Return Items Only When All Sub-Items Are Available
我有一个Item表(本例中是非规范化的),包含一个项目列表,零件以及该零件是否可用。 我想要退回所有可用部件的所有物品。 每个项目可以具有不同数量的部件。 例如:
Item Part Available
A 1 Y
A 2 N
A 3 N
B 1 Y
B 4 Y
C 2 N
C 5 Y
D 4 Y
D 6 Y
D 7 Y
该查询应返回以下内容:
Item Part
B 1
B 4
D 4
D 6
D 7
在此先感谢您的任何帮助。
这是使用Max() Over()
Window聚合函数的一个技巧
SELECT Item,
Part
FROM (SELECT Max([Available])OVER(partition BY [Item]) m_av,*
FROM yourtable) a
WHERE m_av = 'Y'
或使用Group By
和Having
子句
使用IN
子句
SELECT Item,
Part
FROM yourtable
WHERE Item IN (SELECT Item
FROM yourtable
GROUP BY Item
HAVING Count(*) = Sum(Iif(Available = 'Y', 1, 0)))
使用Exists
SELECT Item,
Part
FROM yourtable A
WHERE EXISTS (SELECT 1
FROM yourtable B
WHERE A.Item = B.Item
HAVING Count(*) = Sum(Iif(Available = 'Y', 1, 0)))
使用NOT EXISTS
SELECT Item,
Part
FROM yourtable A
WHERE NOT EXISTS (SELECT *
FROM yourtable B
WHERE A.Item = B.Item
AND B.Available = 'N')
我首先要重新描述要求 - 你想要退回没有任何不可用部件的物品。 一旦你这样说,使用not exists
运算符很容易将需求转换为SQL:
SELECT item, part
FROM parts a
WHERE NOT EXISTS (SELECT *
FROM parts b
WHERE a.item = b.item AND b.available = 'N')
您可以使用NOT IN
OR NOT EXISTS
来实现此目的
不存在
Select item, part
from table as T1
where not exists( select 1 from tbl where item = t1.item and available = 'N')
不在
Select item, part
from table
where item not in( select item from tbl where available = 'N')
使用窗口函数可以读取单个表。
MIN
和MAX
窗口功能
select *
from (
select
t.*,
max(available) over (partition by item) a,
min(available) over (partition by item) b
from your_table t
) t where a = b and a = 'Y';
COUNT
窗口功能:
select *
from (
select
t.*,
count(*) over (partition by item) n1
count(case when available = 'Y' then 1 end) over (partition by item) n2
from your_table t
) t where n1 = n2;
我想指出文中的问题是:“我想要归还所有部件都可用的所有物品”。 但是,您的示例结果包括部件。
如果问题确实只是你想要的项目,那么你可以使用简单的聚合:
select item
from parts
group by item
having min(available) = max(available) and min(available) = 'Y';
如果你确实想要部件的细节,那么其他答案提供了这些信息。
我喜欢它的问题很适合通过不经常使用的语言功能解决:
with cte as (
select * from (values
('A', 1, 'Y'),
('A', 2, 'N'),
('A', 3, 'N'),
('B', 1, 'Y'),
('B', 4, 'Y'),
('C', 2, 'N'),
('C', 5, 'Y'),
('D', 4, 'Y'),
('D', 6, 'Y'),
('D', 7, 'Y')
) as x(Item, Part, Available)
)
select *
into #t
from cte as c;
select *
from #t as c
where 'Y' = all (
select Available
from #t as a
where c.Item = a.Item
)
在这里,我们使用相关子查询和all
关键字来查看是否所有部件都可用。 我的理解是,就像exists
一样,如果找到反例,这将停止。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.