как выбрать строки с одинаковыми column_a, но разными column_b? - PullRequest
0 голосов
/ 28 октября 2019

Я хочу выбрать строки на сервере sql, ниже приведены мои вопросы:

Table1
-------------------------- 
|     Name   |    Type   |
--------------------------
|      A     |     1     |
|      A     |     2     |
|      B     |     1     |
|      B     |     3     |
|      A     |     3     |
|      C     |     1     |
|      C     |     3     |
|      D     |     1     |
|      D     |     2     |
|      D     |     3     |
|      .     |     .     |
|      .     |     .     |

Выберите строки, как показано ниже:

Table2
-------------------------- 
|     Name   |    Type   |
--------------------------
|      A     |     1     |
|      A     |     2     |
|      A     |     3     |
|      D     |     1     |
|      D     |     2     |
|      D     |     3     |
|      .     |     .     |
|      .     |     .     |

Правила выбора ...

Показать имя и тип, тип которого должен иметь 1,2 и 3.

Пример: A имеет 1,2,3 типа, поэтому я бы выбрал его.

Пример: только Bимеет 1,2 типа, поэтому я бы не стал его выбирать.

Ответы [ 5 ]

2 голосов
/ 28 октября 2019

Для этого вы можете использовать оконные функции:

select name, type
from (
    select 
        t.*,
        sum(case when type in (1, 2, 3) then 1 else 0 end)
                over(partition by name) cnt
    from mytable t
) t
where cnt = 3

Предполагается, что каждый кортеж (имя, тип) встречается только один раз в исходной таблице, что соответствует вашим образцам данных.

Демонстрация на DB Fiddle :

name | type
:--- | ---:
A    |    1
A    |    2
A    |    3
D    |    1
D    |    2
D    |    3
1 голос
/ 28 октября 2019

Получите имена с помощью group by name и задайте условие в предложении having:

select * from Table1
where name in (
  select name 
  from Table1
  group by name
  having count(distinct type) = 3
)

Если для столбца Type есть другие значения, отличные от 1, 2, 3, тогда:

select * from Table1
where type in (1, 2, 3) and name in (
  select name 
  from Table1
  where type in (1, 2, 3)
  group by name
  having count(distinct type) = 3
)

См. Демоверсию .

Результаты:

> Name | Type
> :--- | ---:
> A    |    1
> A    |    2
> A    |    3
> D    |    1
> D    |    2
> D    |    3
1 голос
/ 28 октября 2019

Вы можете использовать INNER JOIN s в трех Type столбцах для достижения этой цели:

SELECT Table1.[Name],
       Table1.[Type]
  FROM Table1
    INNER JOIN (
               SELECT [Name]
                 FROM Table1
                 WHERE ([Type] = 1)
               ) A ON A.[Name] = Table1.[Name]
    INNER JOIN (
               SELECT [Name]
                 FROM Table1
                 WHERE ([Type] = 2)
               ) B ON B.[Name] = A.[Name]
    INNER JOIN (
               SELECT [Name]
                 FROM Table1
                 WHERE ([Type] = 3)
               ) C ON C.[Name] = A.[Name]

Это выводит:

Name    Type
A       1
A       2
A       3
D       1
D       2
D       3

Соответствующее sqlfiddle .

Это работает, возвращая строки, содержащие [Type] = 1, а затем ТОЛЬКО совпадающие строки, где [Type] = 2 и [Type] = 3. Затем это присоединяется к вашей основной таблице, и результаты возвращаются.

0 голосов
/ 28 октября 2019

Я дам вам это, это будет работать, если у вас есть:

A 1
A 2
A 3
A 2

Это тогда даст вам только B.

SELECT * 
FROM Table1 
WHERE Name in (
SELECT Name from 
(
   SELECT Name, Type, count(Name) c from Table1 where Type = 1
   GROUP BY Name, Type 
   HAVING count(Name) = 1
   UNION
   SELECT Name, Type, count(Name) c from Table1 where Type = 2
   GROUP by Name, Type 
   HAVING count(Name) = 1
   UNION
   SELECT Name, Type, count(Name) c from Table1 where Type = 3
   GROUP by Name, Type 
   HAVING  count(Name) = 1) t 
GROUP by name
HAVING count(c) = 3)

Вот это DEMO

0 голосов
/ 28 октября 2019

вы можете использовать string_agg, если это SQL Server 2017 и выше или Azure SQL, как показано ниже:

Select * from #yourTable yt join (
    select [name], string_agg([Type], ',') as st_types
    from #YourTable 
    group by [name] ) a 
on yt.name = a.[name] and a.st_types like '%1,2,3%'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...