Уникальные значения с string_agg в более чем 1 столбце - PullRequest
1 голос
/ 02 мая 2020

Я пытаюсь сгруппировать и получить список значений для нескольких столбцов. Вот пример:

City   | State | Income
-------+-------+--------
Salem  |  OH   | 40000
Salem  |  OH   | 45000
Mason  |  OH   | 50000
Dayton |  OH   | 60000
Salem  |  MA   | 40000
Mason  |  MA   | 45000
Mason  |  MA   | 50000
Dayton |  MA   | 70000
Salem  |  PA   | 45000
Mason  |  PA   | 50000
Dayton |  PA   | 60000

Результат, который я ищу:

City   |  States    | Income
-------+------------+--------------
Salem  | OH,MA,PA   | 40000,45000
Mason  | OH,MA,PA   | 50000,45000
Dayton | OH,MA,PA   | 60000,70000

Мне удалось получить это далеко:

City   |  States    | Income
-------+------------+-------------------------
Salem  | OH,MA,PA   | 40000,40000,45000,45000
Mason  | OH,MA,PA   | 50000,50000,50000,45000
Dayton | OH,MA,PA   | 60000,70000,60000

Как мне go отсюда до набора результатов?

City   |  States    | Income
-------+------------+-------------------------
Salem  | OH,MA,PA   | 40000,45000,50000
Mason  | OH,MA,PA   | 50000,45000
Dayton | OH,MA,PA   | 60000,70000

Ответы [ 2 ]

2 голосов
/ 02 мая 2020

Увы, вы не можете использовать string_agg() с distinct. Но вы можете использовать условное агрегирование:

select city,
       string_agg(case when seqnum_state = 1 then state end, ',') as states,
       string_agg(case when seqnum_income = 1 then income end, ',') as incomes
from (select t.*,
             row_number() over (partition by city, state order by state) as seqnum_state,
             row_number() over (partition by city, income order by income) as seqnum_income
      from t
     ) t
group by city;

Здесь - это дБ <> скрипка.

1 голос
/ 02 мая 2020

Вы можете выполнить отдельную группировку по on (Город, штат) и (Город, Доход), чтобы удалить дубликаты, затем вы можете отдельно построить агрегированные строки (Штаты) и (Доходы), и, наконец, вы можете объединить результаты в одну таблица:

DECLARE @tmp TABLE (City VARCHAR(100), State VARCHAR(100), Income int);
INSERT INTO @tmp
VALUES ('Salem' ,'OH', 40000)   ,('Salem' ,'OH', 45000) ,('Mason' ,'OH', 50000) 
      ,('Dayton','OH', 60000)   ,('Salem' ,'MA', 40000) ,('Mason' ,'MA', 45000)
      ,('Mason' ,'MA', 50000)   ,('Dayton','MA', 70000) ,('Salem' ,'PA', 45000) 
      ,('Mason' ,'PA', 50000)   ,('Dayton','PA', 60000)

;with States as(
    select City, state
    from @tmp
    group by  City, state
),
incomes as(
    select City, Income
    from @tmp
    group by  City, Income
)
, states_g as ( 
    select city, STRING_AGG(state,',') as States  
    from states
    group by city
)
, incomes_g as ( 
    select city, STRING_AGG(Income,',') as Incomes  
    from incomes
    group by city
)
select 
    s.City, s.States, i.Incomes 
    from 
        states_g as s
            inner join
        incomes_g as i
            on i.City = s.City

Результаты:

enter image description here

...