Группировка по клиентам и объединение продуктов, открытых в SQL

#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