#sql #sql-server #sql-server-2012
Вопрос:
У меня есть некоторые данные, которые я хочу использовать, чтобы определить, какие продукты открыл каждый клиент. С помощью этих данных я хочу либо создать новый столбец, либо несколько столбцов с указанием этих продуктов. Например, рассмотрим данные ниже.
CustomerKey ProductType
6458 Checking
6458 Savings
6458 Savings
6461 Savings
6461 IRA
Для клиента 6458 я бы хотел либо иметь столбец «Продукты», который объединяет его/ее продукты, как один из способов ниже.
Customer Products Checking/Savings Savings/IRA
6458 Checking/Savings 1 0
6461 Savings/IRA 0 1
Есть ли что-нибудь, что я могу использовать, кроме min/max для типа продукта, что объединит всех участников?
Select Customerkey, producttype
from share
group by customerkey
Комментарии:
1. Если у вас есть доступ к более поздней версии SQL server, вы можете использовать
STRING_AGG
2. Какова логика для двух других столбцов? Например, что происходит с клиентом, у которого есть проверка и ИРА?
3. Эти выходные столбцы не имеют смысла. Зачем вам нужно называть столбцы с содержимым выходных данных продуктов? Почему бы просто не иметь столбец для каждого типа продукта?
4. Это будет то же самое, что и другие. Это либо попадет под категорию «Проверка/ИРА», либо я создам столбец под названием Проверка/ИРА с показателем 1. Мне нужно было бы сделать столбцы для проверки/IRA/Сбережений и т. Д. Я урезал его, чтобы было немного легче. К сожалению, я попробовал String_AGG, и это не сработало. Я хотел бы, чтобы моя компания позволила мне использовать MySQL, чтобы я мог использовать groupconcat
5. Наличие столбцов для каждой комбинации продуктов «возможно» является серьезным анти-шаблоном — что произойдет, если будет 10 продуктов…? Я бы переосмыслил это.
Products
Колонка довольно проста.
Ответ №1:
Логика комбинаций продуктов требует, чтобы вы жестко кодировали каждую возможную комбинацию в условное sum
выражение, как показано ниже:
with p as (
select distinct customerkey customer, Stuff(Products,1,1,'') Products
from t
cross apply (
select distinct '/' ProductType
from t t2
where t2.customerkey=t.customerkey
for xml path('')
)x(Products)
)
select *,
max(case when products='Checking/Savings' then 1 else 0 end) as [Checking/Savings],
max(case when products='IRA/Savings' then 1 else 0 end) as [IRA/Savings]
from p
group by customer, products
Ответ №2:
Я бы сделал что — то подобное. Это использование STRING_AGG для создания списка продуктов. А затем некоторая условная агрегация по известным типам продуктов, чтобы этот столбец возвращал 1 или 0.
create table #Something
(
CustomerKey int
, ProductType varchar(20)
)
insert #Something
select 6458, 'Checking' union all
select 6458, 'Savings' union all
select 6458, 'Savings' union all
select 6461, 'Savings' union all
select 6461, 'IRA'
;
--using a cte to ensure we get only distinct ProductTypes
with PreAggregate as
(
select distinct CustomerKey
, ProductType
from #Something
)
select s.CustomerKey
, Products = STRING_AGG(ProductType, '/') within group(order by ProductType)
, Checking = max(case when ProductType = 'Checking' then 1 else 0 end)
, Savings = max(case when ProductType = 'Savings' then 1 else 0 end)
, IRA = max(case when ProductType = 'IRA' then 1 else 0 end)
from PreAggregate s
group by s.CustomerKey
drop table #Something