【问题标题】:Break down a table to pivot in columns (SQL,PYSPARK)分解表以在列中进行透视(SQL,PYSPARK)
【发布时间】:2023-04-08 10:06:01
【问题描述】:

我在 AWS Glue 中使用 python3.6 的环境 pyspark 中工作。我有这张桌子:

+----+-----+-----+-----+
|year|month|total| loop|
+----+-----+-----+-----+
|2012|    1|   20|loop1|
|2012|    2|   30|loop1|
|2012|    1|   10|loop2|
|2012|    2|    5|loop2|
|2012|    1|   50|loop3|
|2012|    2|   60|loop3|
+----+-----+-----+-----+

我需要得到如下输出:

year    month   total_loop1 total_loop2 total_loop3
2012    1         20           10           50
2012    2         30           5            60

我得到的更接近的是 SQL 代码:

select a.year,a.month, a.total,b.total from test a 
left join test b
on a.loop <> b.loop 
and a.year = b.year and a.month=b.month

到目前为止仍然有输出:

+----+-----+-----+-----+
|year|month|total|total|
+----+-----+-----+-----+
|2012|    1|   20|   10|
|2012|    1|   20|   50|
|2012|    1|   10|   20|
|2012|    1|   10|   50|
|2012|    1|   50|   20|
|2012|    1|   50|   10|
|2012|    2|   30|    5|
|2012|    2|   30|   60|
|2012|    2|    5|   30|
|2012|    2|    5|   60|
|2012|    2|   60|   30|
|2012|    2|   60|    5|
+----+-----+-----+-----+

我该怎么做?非常感谢

【问题讨论】:

    标签: sql sql-server pyspark pyspark-sql aws-glue


    【解决方案1】:

    表格脚本和示例数据

    CREATE TABLE [TableName](
        [year] [nvarchar](50) NULL,
        [month] [int] NULL,
        [total] [int] NULL,
        [loop] [nvarchar](50) NULL
    ) 
    
    INSERT [TableName] ([year], [month], [total], [loop]) VALUES (N'2012', 1, 20, N'loop1')
    INSERT [TableName] ([year], [month], [total], [loop]) VALUES (N'2012', 2, 30, N'loop1')
    INSERT [TableName] ([year], [month], [total], [loop]) VALUES (N'2012', 1, 10, N'loop2')
    INSERT [TableName] ([year], [month], [total], [loop]) VALUES (N'2012', 2, 5, N'loop2')
    INSERT [TableName] ([year], [month], [total], [loop]) VALUES (N'2012', 1, 50, N'loop3')
    INSERT [TableName] ([year], [month], [total], [loop]) VALUES (N'2012', 2, 60, N'loop3')
    

    使用枢轴功能...

    SELECT * 
    FROM   TableName
           PIVOT(Max([total]) 
                FOR [loop] IN ([loop1], [loop2], [loop3]) ) pvt
    

    在线演示:http://www.sqlfiddle.com/#!18/164a4/1/0

    如果您正在寻找动态解决方案,那么试试这个...(动态枢轴)

    DECLARE @cols AS NVARCHAR(max) = Stuff((SELECT DISTINCT ',' + Quotename([loop])
             FROM   TableName
             FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, ''); 
    
    DECLARE @query AS NVARCHAR(max) =  'SELECT * 
                                        FROM   TableName
                                               PIVOT(Max([total]) 
                                                    FOR [loop] IN ('+ @cols +') ) pvt';
    
    EXECUTE(@query) 
    

    在线演示:http://www.sqlfiddle.com/#!18/164a4/3/0

    输出

    +------+-------+-------+-------+-------+
    | year | month | loop1 | loop2 | loop3 |
    +------+-------+-------+-------+-------+
    | 2012 |     1 |    20 |    10 |    50 |
    | 2012 |     2 |    30 |     5 |    60 |
    +------+-------+-------+-------+-------+
    

    【讨论】:

      【解决方案2】:

      你不需要使用join你可以做条件聚合:

      select year, month,
             max(case when loop = 'loop1' then total end) loop1,
             max(case when loop = 'loop2' then total end) loop2,
             max(case when loop = 'loop3' then total end) loop3
      from test a
      group by year, month;
      

      【讨论】:

      • 伟大的解决方案人 我只是验证文档的以下原因,但我想让您知道您的解决方案是我部署的解决方案。谢谢
      • 嗨@AndresAngel,感谢您将我的答案标记为已接受。但您应该考虑选择适合您的答案。
      【解决方案3】:

      您可以使用PIVOT() 将行转换为列:

      SELECT
          year,
          MONTH,
          p.loop1 AS 'total_loop1',
          p.loop2 AS 'total_loop2',
          p.loop3 AS 'total_loop3'
      FROM
          tablename
          PIVOT
              (MAX(total)
                  FOR loop IN ([loop1], [loop2], [loop3])
              ) AS p;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-19
        • 1970-01-01
        • 2018-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-05
        • 2023-01-17
        相关资源
        最近更新 更多