SQL Набор, содержащий другие подмножества вопрос - PullRequest
2 голосов
/ 12 марта 2020

Предположим, у вас есть столбец X со значениями {x1, x2 ... xn}. Теперь каждый x содержит набор значений {a1 ... an}.

Например: x1 ссылки на {a1, a3}, x2 ссылки на {a3}, x3 ссылки на {a1, a2, a3}.

Мне нужно создать запрос, который будет выведите для каждого Xi количество других X, которые имеют набор, содержащийся в наборе Xi, т.е. они содержат подмножество набора Xi.

Вот таблица для примера ввода для этого примера:

table for the sample input for this example.

А вот и ожидаемый результат:

expected result. Как видите, X1 содержит только X2. X2 не содержит других наборов x. И X3 содержит X1 и X2

Я не могу использовать любое процедурное расширение (поэтому нет PLpg sql) или пользовательскую функцию. Это должен быть просто запрос из стандартного SQL.

1 Ответ

2 голосов
/ 12 марта 2020

Следующий запрос может сделать это. В ваш набор записей я добавил новую строку под названием (X4, A10). Я заинтересован, если вы сможете найти другие решения

create table dbo.t(a varchar(10),b varchar(10))

insert into dbo.t values('X1','A1')
insert into dbo.t values('X1','A3')
insert into dbo.t values('X2','A3')
insert into dbo.t values('X3','A1')
insert into dbo.t values('X3','A2')
insert into dbo.t values('X3','A3')
insert into dbo.t values('X4','A10')

-- I have added comments
with cross_prod /*I am building the combination of elements of a with the values of other sets..*/
  as (
  select m.a main_a,n.a other_a,n.b other_b
    from (select distinct a 
            from dbo.t
         ) m
    join dbo.t n
      on m.a<>n.a  
      )
   ,interim_data
   as (
        select  q1.main_a
                ,q1.other_a
                /*Here full_match_flag=0 if all the elements match*/
                ,count(case when q2.main_a is null then 1 end) as full_match_flag 
          from cross_prod q1
        left join (/*This portion gets me the data where the elements match*/
                   select m.a as main_a,n.a as other_a,n.b as other_b
                     from dbo.t m
                     join dbo.t n
                       on m.a<>n.a  
                     where m.b=n.b
                    )q2
            on q1.main_a=q2.main_a
           and q1.other_a=q2.other_a
           and q1.other_b=q2.other_b
        group by q1.main_a
                ,q1.other_a   
       )
select main_a
       ,count(case when full_match_flag=0 then 1 end) as cnt_matches
 from interim_data
group by main_a

+--------+-------------+
| main_a | cnt_matches |
+--------+-------------+
| X1     |           1 |
| X2     |           0 |
| X3     |           2 |
| X4     |           0 |
+--------+-------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...