【问题标题】:Dynamic pivot table for every single row (MySql)每行的动态数据透视表(MySql)
【发布时间】:2019-02-04 14:26:15
【问题描述】:

我有一张客户喜欢的桌子:

ID       Type       Date          Address         SSN
RT124    MASTER     12/15/2005    7 Hill st       12345 
RT542    MASTER     06/14/2006    7 Hill st       12345
HT457    UNIQUE     10/27/2009    10 PARK WAY     24569   
QA987    UNIQUE     08/28/2010    10 PARK WAY     24569
AH825    UNIQUE     10/12/2012    10 PARK WAY     24569
14837    SINGLE     05/05/2010    2 TED ROAD      11111
24579    MARRIED    06/24/2014    2 TED ROAD      11111

我想要的是为每个重复的地址和 SSN 创建一个新列 +#,并且ID #1 总是应该是最近的日期。

注意:此表只有基于地址和SSN的重复行,但唯一的ID,不需要任何总和。

所以输出应该是这样的(点击图片放大):

我做了一些研究并尝试了一些示例,但没有任何工作可以得到这个输出。

我将不胜感激!

【问题讨论】:

  • 试图在 SQL 中解决这种枢轴问题会很复杂,可能会导致代码难以维护。这个问题实际上是一个XY Problem。相反,我建议您仅通过 ORDER BY SSN, Date DESC 查询数据库并在您的客户端应用程序中处理数据透视。为工作使用正确的工具。

标签: mysql sql dynamic pivot prepared-statement


【解决方案1】:

您需要枚举行并聚合。在 MySQL(V8 之前)中,它看起来像:

select address, ssn,
       max(case when rn = 1 then id end) as id1,
       max(case when rn = 1 then type end) as type1,
       max(case when rn = 1 then date end) as date1,
       max(case when rn = 2 then id end) as id2,
       max(case when rn = 2 then type end) as type2,
       max(case when rn = 2 then date end) as date2
       . . .
from (select c.*,
             (@rn := if(@as = concat_ws(':', address, ssn), @rn + 1,
                        if(@as := concat_ws(':', address, ssn), 1, 1)
                       )
             ) as rn
      from (select c.* from customers c order by address, ssn, date desc) c cross join
           (select @as := '', @rn := 0) params
     ) c
group by address, ssn;

请注意,这不会重复 addressssn。这似乎没什么用,但您当然可以在每组中重复这些列。

【讨论】:

    【解决方案2】:

    地址可以复制的次数是否有限制?如果存在已知限制,则每个重复项可以有多个左连接。如果您知道只有 6 个或更少的重复项,以下将是一个解决方案:

    with a as (
    select 
        ID
        ,type
        ,date
        ,address
        ,SSN
        row_number() over(partition by address, SSN order by date desc) as R
    from Customers
    )
    
    select 
        a.id ID1
        ,a.type TYPE1
        ,a.date DATE1
        ,a.address ADDRESS1
        ,a.ssn SSN1
    
        ,b.id ID2
        ,b.type TYPE2
        ,b.date DATE2
        ,b.address ADDRESS2
        ,b.ssn SSN2
    
        ,c.id ID3
        ,c.type TYPE3
        ,c.date DATE3
        ,c.address ADDRESS3
        ,c.ssn SSN3
    
        ,d.id ID4
        ,d.type TYPE4
        ,d.date DATE4
        ,d.address ADDRESS4
        ,d.ssn SSN4
    
        ,e.id ID5
        ,e.type TYPE5
        ,e.date DATE5
        ,e.address ADDRESS5
        ,e.ssn SSN5
    
        ,f.id ID6
        ,f.type TYPE6
        ,f.date DATE6
        ,f.address ADDRESS6
        ,f.ssn SSN6
    
    from a
    left join
        (select * from a
        where r=2
        ) b
    on a.address=b.address and a.ssn=b.ssn
    
    left join
        (select * from a
        where r=3
        ) c
    on a.address=c.address and a.ssn=c.ssn
    
    left join
        (select * from a
        where r=4
        ) d
    on a.address=d.address and a.ssn=d.ssn
    
    left join
        (select * from a
        where r=5
        ) e
    on a.address=e.address and a.ssn=e.ssn
    
    left join
        (select * from a
        where r=6
        ) f
    on a.address=f.address and a.ssn=f.ssn
    
    where r=1
    

    如果超过 6 个,只需在 select 语句中添加另一组列即可:

        ,f.id ID6
        ,f.type TYPE6
        ,f.date DATE6
        ,f.address ADDRESS6
        ,f.ssn SSN6
    

    和一个新的左连接到 from 语句:

    left join
        (select * from a
        where r=6
        ) f
    on a.address=f.address and a.ssn=f.ssn
    

    【讨论】:

    • 现在是 6,但未来可能会更多。
    • 您可以为每个新副本添加左连接和一组列。我会编辑 6 点。
    猜你喜欢
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多