如何使用 case when 和 partition by in SQL 将多个值合并为一个值?

How to consolidate multiple values into one value using case when and partition by in SQL?

我有一个 table,其中在一个字段中包含 3 个不同的名称、这些名称关联的相应帐户、唯一 ID、每对的总计数以及基于总计数的排名列价值。此处示例:

LOGO     |  Account |  ID    |   Count_Per_Logo   |  Rank

Walmart     Acct_A     ABC          3                 1
Walmart     Acct_A     DEF          3                 1
Walmart     Acct_A     GHI          3                 1
Vudu        Acct_A     JKL          1                 2
Bonobos     Acct_A     MNO          1                 2

我的目标是 'consolidate' LOGO 字段变成一个帐户的一个徽标 - 因此对于每个唯一 ID - 它们应该只与 1 个徽标相关联(而不是上面显示的 3 个)。

期望的输出

LOGO     |  Account |  ID    |   Count_Per_Logo   |  Rank   | Consolidated_LOGO

Walmart     Acct_A     ABC          3                 1       Walmart     
Walmart     Acct_A     DEF          3                 1       Walmart     
Walmart     Acct_A     GHI          3                 1       Walmart     
Vudu        Acct_A     JKL          1                 2       Walmart     
Bonobos     Acct_A     MNO          1                 2       Walmart     

现在我正在使用带有分区依据的计数来获得排名 - 但我不确定如何根据排名值创建一个具有 'desired logo' 的新字段 - 滞后函数是这有必要吗?任何帮助将不胜感激

当前逻辑

SELECT LOGO, ACCOUNT, ID FROM
(SELECT *, DENSE_RANK() OVER (PARTITION BY ACCOUNT ORDER BY LOGO_NAME_CNT DESC) AS LOGO_RANK
FROM
(SELECT *, count(ACCOUNT) over (partition by LOGO) AS LOGO_NAME_CNT FROM "TABLE1" WHERE ACCOUNT = 'Acct_A')
)
WHERE LOGO_RANK = 1

看来你的基础 SQL 是:

SELECT
    a.*
    ,dense_rank() over (partition by account order by count_per_logo desc) as rank
FROM (
    SELECT 
        logo
        ,account
        ,id
        ,count(logo) over (partition by account, logo) as count_per_logo
    FROM VALUES 
        ('walmart', 'acct_a', 'abc'),   
        ('walmart', 'acct_a', 'def'), 
        ('walmart', 'acct_a', 'ghi'),
        ('vudu', 'acct_a', 'jkl'),
        ('bonobos', 'acct_a', 'mno')
        v(logo, account, id)
) AS a
ORDER BY 4 DESC, 5;

那么您只需添加一个 FIRST_VALUE,例如:

SELECT
    a.*
    ,dense_rank() over (partition by account order by count_per_logo desc) as rank
    ,first_value(logo) over (partition by account order by count_per_logo desc) as Consolidated_LOGO
FROM (
    SELECT 
        logo
        ,account
        ,id
        ,count(logo) over (partition by account, logo) as count_per_logo
    FROM VALUES 
        ('walmart', 'acct_a', 'abc'),   
        ('walmart', 'acct_a', 'def'), 
        ('walmart', 'acct_a', 'ghi'),
        ('vudu', 'acct_a', 'jkl'),
        ('bonobos', 'acct_a', 'mno')
        v(logo, account, id)
) AS a
ORDER BY 4 DESC, 5;

这给出::

LOGO ACCOUNT ID COUNT_PER_LOGO RANK CONSOLIDATED_LOGO
walmart acct_a abc 3 1 walmart
walmart acct_a def 3 1 walmart
walmart acct_a ghi 3 1 walmart
vudu acct_a jkl 1 2 walmart
bonobos acct_a mno 1 2 walmart

只要您没有关系,Simeon 的回答就应该有效。其实,如果你不在乎领带,那就更简单了

select logo,
       account,
       id,
       mode(logo) over (partition by account) as consolidated_logo
from your_table;

如果您希望为与计数有关的每个徽标实例复制结果集,请考虑以下内容

with cte as

(select logo, account 
 from your_table 
 group by logo, account
 qualify max(count(*)) over (partition by account)=count(*))


select a.*, b.logo as consolidated_logo
from your_table a
join cte b on a.account=b.account
order by b.logo;