2017-01-28 2 views
1

У меня есть таблица элементов (денормализованная для этого примера), содержащая список элементов, частей и доступность этой части. Я хочу вернуть все элементы, для которых доступны все части. Каждый элемент может иметь различное количество деталей. Например:SQL Server - возвращаемые элементы только при наличии всех подпозиций

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  

Заранее спасибо за любую помощь.

ответ

0

Вот один трюк с использованием 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') 
0

Я хотел бы начать с перефразируя требование - вы хотите возвратить детали, которые не имеют каких-либо частей, которые не доступны. После того, как вы выразились так, что легко перевести требование SQL с помощью not exists оператора:

SELECT item, part 
FROM parts a 
WHERE NOT EXISTS (SELECT * 
        FROM parts b 
        WHERE a.item = b.item AND b.available = 'N') 
0

U можно использовать NOT IN ИЛИ NOT EXISTS для достижения этой цели

НЕ СУЩЕСТВУЕТ

Select item, part 
from table as T1 
where not exists(select 1 from tbl where item = t1.item and available = 'N') 

NOT IN

Select item, part 
from table 
where item not in(select item from tbl where available = 'N') 
0

Используя функцию окна, читается одна таблица.

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; 
+0

Первый метод неправильный, когда каждая запись является 'N', тогда она вернет товар –

+0

@Prdp большое спасибо. Починил это. – GurV

0

Я хочу отметить, что вопрос в тексте: «Я хочу, чтобы вернуть все элементы, для которых все детали доступны ». Однако результаты вашего примера включают части.

Если вопрос действительно, что вы хотите только элементы, то вы можете использовать простую агрегацию:

select item 
from parts 
group by item 
having min(available) = max(available) and min(available) = 'Y'; 

Если вы действительно хотите подробно на деталях, а также, то другие ответы предоставить эту информацию.

0

я, как это проблемы хорошо поддаются решаемые редко используемых функций языка:

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, это остановится, если найдет встречный пример.

Смежные вопросы