Разбейте таблицу для поворота в столбцах (SQL, PYSPARK) - PullRequest
0 голосов
/ 11 мая 2018

Я работаю в среде pyspark с python3.6 в AWS Glue. У меня есть эта таблица:

+----+-----+-----+-----+
|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|
+----+-----+-----+-----+

Как я мог это сделать? Большое спасибо

Ответы [ 3 ]

0 голосов
/ 11 мая 2018

Вы можете использовать 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;
0 голосов
/ 11 мая 2018

Скрипт таблицы и пример данных

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')

Использование функции Pivot ...

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 |
+------+-------+-------+-------+-------+
0 голосов
/ 11 мая 2018

Вам не нужно использовать 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;
...