繁体   English   中英

SQL Server-仅在所有子项可用时返回项目

[英]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 ByHaving子句

使用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')

使用窗口函数可以读取单个表。

MINMAX窗口功能

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM