#sql #sql-server
#sql #sql-сервер
Вопрос:
Я сталкиваюсь с проблемой, когда необходимо отфильтровывать повторяющиеся строки, ограничивая некоторые критерии для другого столбца, например, отфильтровывать строки, дублируемые MappingID
Date
столбцами и , но для столбца должно быть как значение NULL, так и значение NOT NULL Subject
.
Исходные данные:
| Subject | MappingID | Date | Qty |
-------------- ----------- ------------ --------
| NULL | M1 | 2020-11-01 | 10 |
| S1 | M1 | 2020-11-01 | 20 |
| S2 | M2 | 2020-11-01 | 5 |
| S2 | M2 | 2020-11-01 | 6 |
| NULL | M1 | 2020-11-02 | 7 |
Ожидаемый результат ( Subject
сводный, M2
не включен в набор результатов, поскольку тема одна и та же) :
| MappingID | Date | Subject1 | Subject2 | Subject1Qty | Subject2Qty |
----------- ------------ ---------- ---------- ------------- -------------
| M1 | 2020-11-01 | S1 | NULL | 20 | 10 |
Комментарии:
1. Вы не можете произвольно выполнять поворот в T-SQL: вам необходимо предварительно определить имена сводных столбцов. Но еще лучше вообще не сводить. Вам обязательно нужно сводить результирующие данные?
2. Может ли a
mapping_id
иметь более двух объектов в одном и том жеday
, напримерNULL, S1, S2
? Если да, то каковы ограничения и каковы ваши ожидаемые результаты для такого сценария?3. Может ли a
mapping_id
иметь несколько строк для одного и того же объекта в одном и том жеday
и при этом соответствовать другим вашим критериям? НапримерNULL, NULL, S1, S1
? Если да, то каковы ваши ожидаемые результаты для такого сценария?4. @Dai Мне нужно сравнить эти NULL и NOT NULL Subject, есть ли у вас какие-либо другие предложения, если не использовать pivot?
5. @MatBailie, да, может быть более двух объектов, для тех, которые не являются нулевыми, мы можем объединить их как один
Ответ №1:
Используйте group by
и having
:
select mappingid, date,
max(case when rn = 1 then subject end) as subject1,
max(case when rn = 2 then subject end) as subject2,
max(case when rn = 1 then qty end) as qty1,
max(case when rn = 2 then qty end) as qty2
from (
select t.*,
row_number() over(partition by mappingid, date order by subject) rn
from mytable t
) t
group by mappingid, date
having max(subject) is not null
and max(case when subject is null then 1 else 0 end) = 1
Ответ №2:
На самом деле вы можете сделать это без подзапроса — при условии, что у вас есть две строки для каждого идентификатора и даты:
select mappingid, date,
max(subject) as subject_1,
max(case when subject is not null then qty end) as qty_1,
null as subject_2,
max(case when subject is null then qty end) as qty_2
from t
group by mappingid, date
having count(subject) = 1 and count(*) = 2;