#sql-server
#sql-сервер
Вопрос:
Я ищу способ группировки по двум столбцам, где первый столбец группировки имеет более одного уникального значения для второго столбца группировки. Ниже приведена примерная таблица с образцами данных.
CREATE TABLE [dbo].[MyTable](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Type] [varchar](20) NOT NULL,
[UnitOfMeasure] [varchar](20) NULL,
CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED
(
[ID] ASC
) ON [PRimary]
) ON [PRimary];
INSERT INTO [MyTable] (Type, UnitOfMeasure)
VALUES ('height', 'cm')
, ('distance', 'km')
, ('weight', 'kg')
, ('Glucose', 'mg/dL')
, ('weight', 'kg')
, ('Duration', 'hours')
, ('Glucose', 'mg/dL')
, ('Glucose', 'mg/dL')
, ('height', 'cm')
, ('Allergy', 'kUnits/L')
, ('Volume', 'mL')
, ('height', 'inch')
, ('height', 'cm')
, ('Chloride', 'mmol/L')
, ('Volume', 'cup')
, ('distance', 'km')
, ('Volume', 'cup')
, ('Duration', 'hours')
, ('Chloride', 'mmol/L')
, ('Duration', 'minutes');
Желаемый вывод выглядит следующим образом.
Type UnitOfMeasure
Duration hours
Duration minutes
height cm
height inch
Volume cup
Volume mL
Этот вывод включает длительность, поскольку он имеет две единицы измерения. Однако он не включает ни вес, ни хлорид, поскольку он имеет только одну единицу измерения.
Комментарии:
1. Кажется странным, что у вас есть повторяющиеся строки; вы рассматривали возможность исправления этого?
2. Чтобы упростить вопрос, я не включил другие столбцы, которые, по вашему мнению, выглядят дублирующимися. Цель запроса — идентифицировать типы, которые имеют конфликтующие единицы измерения, например, тип, который имеет единицы измерения cm и mL. таблица, с которой я работаю, содержит миллионы строк с более чем 10 000 типами. Просто нужно ограничить количество проверяемых типов. Предоставленный запрос привел к сокращению количества типов до чуть более 700.
Ответ №1:
Вы можете использовать CTE для получения a DISTINCT
COUNT
, а затем использовать an EXISTS
с дальнейшим DISTINCT
. Я ожидаю, что это будет немного дороже, и в идеале вы, вероятно, захотите обратиться к тем повторяющимся строкам, которые у вас есть.
WITH Counts AS(
SELECT [Type],
COUNT(DISTINCT UnitOfMeasure) AS DistinctMeasures
FROM dbo.MyTable
GROUP BY [Type])
SELECT DISTINCT
[Type],
UnitOfMeasure
FROM dbo.MyTable MT
WHERE EXISTS (SELECT 1
FROM Counts C
WHERE C.[Type] = MT.[Type]
AND C.DistinctMeasures > 1);
Комментарии:
1. Спасибо! Намного проще, чем я ожидал.
Ответ №2:
Вы можете сделать это с помощью EXISTS:
SELECT DISTINCT t.[Type], t.[UnitOfMeasure]
FROM [MyTable] t
WHERE EXISTS (
SELECT 1 FROM [MyTable]
WHERE [Type] = t.[Type] AND [UnitOfMeasure] <> t.[UnitOfMeasure]
)
Смотрите демонстрацию.
Результаты:
> Type | UnitOfMeasure
> :------- | :------------
> Duration | hours
> Duration | minutes
> height | cm
> height | inch
> Volume | cup
> Volume | mL
Ответ №3:
Это можно сделать только с помощью оконных функций. Просто сравните минимальные и максимальные единицы измерения для каждого типа: если они отличаются, то вы знаете, что у вас есть по крайней мере два разных значения, и вы можете сохранить соответствующие строки:
select distinct type, unitofmeasure
from (
select t.*,
min(unitofmeasure) over(partition by type) min_unit,
max(unitofmeasure) over(partition by type) max_unit
from mytable t
) t
where min_unit <> max_unit