#sql #sql-server #ssms
#sql #sql-server #ssms
Вопрос:
У меня есть таблица из нескольких неполных записей, каждая из которых ссылается на определенного клиента — тип клиента (Тип), годовые закупки (A), местоположение клиента (B), вторичный подрядчик (C), частота (D) и т.д. Эти записи действуют как моментальные снимки несовершенной информации о каждом клиенте и им присваивается год и уникальный snapshotID (snapID).
Моя цель — создать единую запись, состоящую из последних ненулевых, ненулевых значений каждого поля (вместе с годом, связанным с этим snapshotID) для каждого клиента и типа клиента (каждый CustomerID может иметь несколько типов клиентов), и в противном случае она должна быть пустой.
В разные моменты моего исследования я полагал, что решение связано с разделами, подзапросами, сводными, регистром или простым порядком / группой по, но я слишком новичок, чтобы разобраться в разных вариантах использования.
Пример данных:
[custID] [Type] [snapID] [A] [B] [C] [D] [Year]
1025 InPerson 5 0 (NULL) Cavs Weekly 2020
1025 InPerson 6 275 (NULL) Heat Weekly 2019
1025 InPerson 7 600 Cleveland Cavs (NULL) 2018
7256 Online 8 (NULL) Akron (NULL) (NULL) 2020
7256 InPerson 9 375 (NULL) Nets (NULL) 2020
7256 Online 10 400 (NULL) Thunder Monthly 2015
7256 InPerson 11 (NULL) (NULL) Magic (NULL) 2014
Желаемый результат:
[custID] [Type] [A] [AYear] [B] [BYear] [C] [CYear] [D] [DYear]
1025 InPerson 275 2019 Cleveland 2018 Cavs 2020 Weekly 2020
7256 InPerson 375 2020 (NULL) (NULL) Nets 2020 (NULL) (NULL)
7256 Online 400 2015 Akron 2020 Thunder 2015 Monthly 2014
Комментарии:
1. Извинения. Я только что отредактировал вопрос. Помеченный SQL Server и SSMS. Спасибо за совет.
Ответ №1:
Это может быть сделано с использованием некоторой вложенной конструкции подзапроса, которую будет сложно понять и отладить. Поэтому, если ваша платформа позволяет, я бы пошел другим путем, используя пользовательские функции.
Для точного синтаксиса обратитесь к документации вашей СУБД. Я бы определил такие функции, как
create function maxAYear (
@custID int,
@type varchar(...)
)
return select max(Year)
from your_table
where custID = @custID
and @type = type
and A is not null
and A <> 0
create function maxA (
@custID int,
@type varchar(...)
)
return select A
from my_table
where custID = @custID
and type = @type
and year = maxAYear(@custID, @type)
а затем создайте мою таблицу результатов как
select custID, type, maxA(custID, type), maxAYear(custID, type), ...
from (
select distinct custID, type
from my_table
) a
Я знаю, что некоторые люди не рекомендуют использовать пользовательские функции. Но я использую их довольно часто без каких-либо проблем, и у них есть два преимущества:
- Они обеспечивают модульную конструкцию, которую легко понять,
- они могут использоваться повторно,
- их можно протестировать отдельно, что не относится к вложенным подзапросам.
Ответ №2:
Это отвечает на исходную версию вопроса.
В стандартном SQL вы можете использовать last_value(ignore nulls)
:
select t.*
from (select custid, type,
last_value(a ignore nulls) over (partition by custid, type order by year) as a,
last_value(case when a is not null then year end ignore nulls) over (partition by custid, type order by year) as ayear,
last_value(b ignore nulls) over (partition by custid, type order by year) as b,
last_value(case when b is not null then year end ignore nulls) over (partition by custid, type order by year) as byear,
last_value(c ignore nulls) over (partition by custid, type order by year) as c,
last_value(case when c is not null then year end ignore nulls) over (partition by custid, type order by year) as cyear,
last_value(d ignore nulls) over (partition by custid, type order by year) as d,
last_value(case when d is not null then year end ignore nulls) over (partition by custid, type order by year) as dyear,
row_number() over (partition by custid, type order by year desc) as seqnum
from t
) t
where seqnum = 1;
Вот скрипка db<> .
Ваш вопрос помечен как «SQL», что относится к стандартному SQL. И это стандартное решение SQL. Если это не работает в вашей конкретной базе данных, задайте новый вопрос с соответствующим тегом базы данных.
Комментарии:
1. Большое вам спасибо, Гордон, за то, что вы столкнулись с проблемой, это подталкивало меня к моим пределам. К сожалению (о чем я, как истинный n00b, забыл упомянуть), я работаю на SQL Server вместо Oracle, и часть запроса «last_value ([столбец] игнорирует нули)» вызывает у меня приступы. Я пытаюсь найти SQL Server, эквивалентный этой команде, чтобы спасти работу, которую вы здесь проделали. Еще раз спасибо, я опубликую, когда найду решение!
2. @aFellowChucker . , , Я бы посоветовал вам задать новый вопрос с четким объяснением и соответствующим тегом.
3. Я просто отредактировал вопрос и пометил более подходящим образом. Еще раз спасибо за вашу помощь.