Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Получить группы в разрезе одного поля по уникальным значениям другого  [new]
Некая группа
Guest
Дана выборка вида:
select t.s, t.n from (
  values
    ('A', 1),('A', 2),('A', 3),('A', 4),('A', 5),
    ('B', 1),('B', 2),('B', 4),('B',3),('B',1),
    ('C', 2),('B', 4),
    ('D', 1),('D', 3),('D', 4),('D', 6),('D', 5),
)t(s,n)

Нужно из этой выборки получить те записи, в пределах разбиения которых по полю s совокупность полей n содержит все значения из заданного списка - т.е. для значений 1,3,5 из исходной мы должны полчить выборку со значениями A,D. Пока получилось так:
declare
  @t_n table (n int primary key);
insert into @t_n
  select n from (values (1),(3),(5)) t(n);
declare
  @t table (
    s varchar(1),
    n int
  );
insert into @t
  select t.s, t.n from (
    values
      ('A', 1),('A', 2),('A', 3),('A', 4),('A', 5),
      ('B', 1),('B', 2),('B', 4),('B',3),('B',1),
      ('C', 2),('С', 4),
      ('D', 1),('D', 3),('D', 4),('D', 6),('D', 5)
  )t(s,n);
-- ==============================
;with cte as (
  select distinct s,n from @t
  where n=any(select n from @t_n)
), cte2 as (
  select s,n,count(n) over(partition by s) cnt
  from cte
)
select distinct s from cte2 where cnt=(select count(n) from @t_n)

но как-то это мне не очень - гроздковато, и план исполнения не нравится. Можно ли сделать как-то по-другому?
23 янв 14, 08:55    [15454953]     Ответить | Цитировать Сообщить модератору
 Re: Получить группы в разрезе одного поля по уникальным значениям другого  [new]
invm
Member

Откуда: Москва
Сообщений: 9646
Реляционное деление
23 янв 14, 09:45    [15455121]     Ответить | Цитировать Сообщить модератору
 Re: Получить группы в разрезе одного поля по уникальным значениям другого  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
FacePalm.
Права купил. Водить не купил.
Работайте над ошибками мышления и понимания.
Некая группа
declare
  @t_n table (n int primary key);
declare
  @t table ( -- где ключ
    s varchar(1),
    n int
  );

-- ==============================
;with cte as (
  select distinct s,n from @t  -- зачем тут distinct ?! Значения всё равно остаются уникальными
  where n=any(select n from @t_n)
), cte2 as (
  select s,n,count(n) over(partition by s) cnt
  from cte
)
select distinct s from cte2 where cnt=(select count(n) from @t_n)

-- Зачем вообще так выяпываться? Вместо группировки - оконные функции, а потом всё равно distinct ?!
-- Знаем окошки, но не знаем HAVING ? окошки - это последнее что надо знать
но как-то это мне не очень - гроздковато, и план исполнения не нравится. Можно ли сделать как-то по-другому?
Нужно не придумывать запрос, нужно понимать реляционную алгебру. Видеть в ней \ ею.

Остальное уже сказано.
24 янв 14, 00:42    [15460076]     Ответить | Цитировать Сообщить модератору
 Re: Получить группы в разрезе одного поля по уникальным значениям другого  [new]
Некая группа
Guest
Mnior,

Mnior
declare
  @t table ( -- где ключ
    s varchar(1),
    n int
  );

Она утонула его нет. Читайте внимательнее постановку задачи. Поле s неуникально, поле n неуникально, более того, поле n неуникально в разрезе по s. Или вы к тому, что тут надо было объявить суррогатный ключ? Который далее бы нигде не использовался - объявить только для того, шопбыло. Для тестового примера, который просто демонстрирует суть проблемы, это, по-моему, слишком.
Mnior
  select distinct s,n from @t  -- зачем тут distinct ?! Значения всё равно остаются уникальными

См. выше.
Mnior
-- Зачем вообще так выяпываться? Вместо группировки - оконные функции, а потом всё равно distinct ?!

Потому что результирующая выборка из cte2 с сохранением условия where cnt=(select count(n) from @t_n) будет такой:
sncnt
A13
A33
A53
D13
D33
D53

а мне нужно
s
A
D

Нет, я, собственно, не спорю с тем, что запрос в стартовом постинге был написан криво. Только вот большая часть ваших претензий, мягко говоря, необоснована.
Mnior
Работайте над ошибками мышления и понимания.

Мда.

invm, спасибо, то, что нужно.
24 янв 14, 06:29    [15460553]     Ответить | Цитировать Сообщить модератору
 Re: Получить группы в разрезе одного поля по уникальным значениям другого  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Некая группа
Или вы к тому, что тут надо было объявить суррогатный ключ? Который далее бы нигде не использовался - объявить только для того, шопбыло. Для тестового примера, который просто демонстрирует суть проблемы, это, по-моему, слишком.
Почему не использоваться?
Это же суть задачи. Его не уникальность выходит за рамки поставленного вопроса.
И да, именно для примера как раз демонстрирует суть. Так что претензия обоснованная.
Некая группа
Читайте внимательнее постановку задачи.
Читал внимательно. Никаких намёков на неуникальность нет.
Некая группа
Потому что результирующая выборка из cte2 с сохранением условия where cnt=(select count(n) from @t_n) будет такой:
Причём тут это?!
Зачем в cte2 не группировать по полю s, используя вместо простой агригатки - оконную функцию, чтоб потом же сразу же группировать через distinct?
Вы что этого не поняли? Или это необоснованный вопрос?

declare
  @t_n table (n int primary key);
insert into @t_n
  select n from (values (1),(3),(5)) t(n);
declare
  @t table (
    s varchar(1),
    n int
    ,primary key (s,n)
  );
insert into @t
  select distinct t.s, t.n from (
    values
      ('A', 1),('A', 2),('A', 3),('A', 4),('A', 5),
      ('B', 1),('B', 2),('B', 4),('B',3), ('B',1), -- а вот заметил, тут дубль, спасиб что замаскировали
                                          -- несущественное замечание про первый дистинкт можно пропустить
      ('C', 2),('С', 4),
      ('D', 1),('D', 3),('D', 4),('D', 6),('D', 5)
  )t(s,n);
-- ==============================
;with cte as (
  select s,n from @t t
  where Exists(select * from @t_n n where t.n = n.n)
)
  select s, count(*) cnt
  from cte
  group by s
  having count(*) = (select count(*) from @t_n)
Некая группа, теперь понятно, что я имел ввиду, и почему ваш вариант просто ахтунг?
24 янв 14, 12:39    [15462091]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить