#sql #sql-server #case #windowing
#sql #sql-сервер #регистр #управление окнами
Вопрос:
Первый раз запрашивающий — у меня возникли некоторые проблемы с сочетанием логики обращения и управления окнами в SQLServer 2012. Мне нужно выровнять структуру данных, показанную ниже, поэтому впоследствии я буду использовать инструкции MAX для этих результатов. Я использую логику case / when, чтобы указать «Владельца» для каждого xID. Моя проблема в том, что я постоянно получаю неправильные результаты, и я не смог определить, что я делаю неправильно.
Вот логика case / when и структура таблицы. Для столбца ‘Owner’ мне нужно оценить три условия, и я пытался использовать FIRST_VALUE() для выбора выходных данных оператора case. Логика в операторе case работает правильно, но когда я пытаюсь применить значение к каждому из XID с помощью функции windowing, она возвращает неправильное значение.
FIRST_VALUE(case
when [partnerType] = 'Giver' and [partnerAgree] = 'True' then [partnerGroup]
when [partnerType] = 'Impacted' and [partnerAgree] = 'True' then [partnerGroup]
when [Stakeholder No#] = 1 and [partnerAgree] <> 'True' then [partnerGroup]
else Null end) over (partition by [xID] order by [yID])
as 'Owner'
Desired Results --------------------------
|xID|yID| Owner |partnerType| partnergrp|partnerAgree
|100| 1| grp_Banana|Taker |grp_Apple |TRUE
|100| 2| grp_Banana|Giver |grp_Banana |TRUE
|100| 3| grp_Banana|Taker |grp_Banana |FALSE
|101| 1| grp_Carrot|Taker |grp_Carrot |TRUE
|101| 2| grp_Carrot|Giver |grp_Danish |FALSE
|101| 3| grp_Carrot|Taker |grp_Banana |TRUE
|101| 4| grp_Carrot|Taker |grp_Danish |FALSE
Results I'm getting --------------------------
|xID|yID| Owner |partnerType| partnergrp|partnerAgree
|100| 1| grp_Apple |Taker |grp_Apple |TRUE
|100| 2| grp_Apple |Giver |grp_Banana |TRUE
|100| 3| grp_Apple |Taker |grp_Banana |FALSE
|101| 1| grp_Carrot|Taker |grp_Carrot |TRUE
|101| 2| grp_Carrot|Giver |grp_Danish |FALSE
|101| 3| grp_Carrot|Taker |grp_Banana |TRUE
|101| 4| grp_Carrot|Taker |grp_Danish |FALSE
Первая таблица показывает результаты, как я их ожидал, но код выдает значения во второй таблице. Пример: для xID = 100 я бы ожидал, что владельцем будет grp_Banana, но мой код возвращает grp_Apple. Для xID = 101 я получаю правильный ответ, но по неправильной причине. Похоже, что функция windowing принимает первый идентификатор yID для любого результирующего набора.
Спасибо, любая помощь приветствуется. Кроме того, я открыт для того, чтобы не использовать функцию windowing, это просто кажется правильным направлением.
Комментарии:
1. Добро пожаловать в Staackoverflow! Я думаю, было бы очень полезно, если бы мы могли видеть выходные данные вашего текущего оператора case. Вы предоставили ожидаемые результаты, и это хорошо. Добавление некоторых образцов данных также может быть полезным.
2. @BrianBlanton . . . Пожалуйста, опишите логику для
owner
. Вы показываете код, который не работает, но нигде не объясняете, чего вы на самом деле хотите. Кроме того, тег базы данных также полезен.3. Какая СУБД??? SQL — это просто язык, используемый несколькими поставщиками СУБД.
4. Спасибо за отзыв, добавил дополнительные детали к описанию.
Ответ №1:
Это сложно, если ваша база данных не поддерживает ignore null
аргумент s. Вы можете сделать это с помощью двух оконных функций:
max(case when yid = yid_special then partnerGroup end) over (partition by xid) as Owner
from (select . . . ,
min(case when partnerType = 'Giver' and [partnerAgree] = 'True' then yid
when partnerType = 'Impacted' and [partnerAgree] = 'True' then yid
when [Stakeholder No#] = 1 and [partnerAgree] <> 'True' then yid
end) over (partition by xid) as yid_special
Вы также можете написать это с помощью first_value()
:
first_value(partnerGroup) over
(partition by xid
order by (case when partnerType = 'Giver' and [partnerAgree] = 'True' then yid
when partnerType = 'Impacted' and [partnerAgree] = 'True' then yid
when [Stakeholder No#] = 1 and [partnerAgree] <> 'True' then yid
else 999999
end)
) as owner
Комментарии:
1. Спасибо @Gordon-Linoff, я использовал ваше второе предложение в качестве основы для решения моей проблемы. Я не думаю, что решил бы это так быстро без вашего отзыва. Я также добавил ваш блог в свой список чтения.
Ответ №2:
Используя предложение от @Gordon-Linoff, я смог решить свою проблему. Вот измененный код. Увидев, как Гордон использует оператор case в порядке, я понял, почему мой код иногда выбирал неправильные значения. Я благодарен ему за ответ, поскольку я только что основывался на его подходе. Очень признателен.
, FIRST_VALUE(
case
when [partnerType] = 'Remediator' and [partnerAgree] = 'True' then [partnerGroup]
when [partnerType] = 'Impacted' and [partnerAgree] = 'True' then [partnerGroup]
when [yID] = 1 and [partnerAgree] <> 'True' then [partnerGroup]
else [partnerGroup] end)
over
(partition by [Incident ID] order by
case
when [partnerType] = 'Remediator' and [partnerAgree] = 'True' then 1
when [partnerType] = 'Impacted' and [partnerAgree] = 'True' then 2
when [yID] = 1 and [partnerAgree] <> 'True' then 3
else 100
end
)
as 'Owner'