Повернуть таблицу базы данных - PullRequest
2 голосов
/ 14 февраля 2020

Представьте, что у меня есть таблица базы данных в следующем формате:

╔══════════════════════╗
║ Name   Quarter Sales ║
╠══════════════════════╣
║ Joe    Q1      700   ║
║ Joe    Q2      650   ║
║ Joe    Q3      660   ║
║ Bill   Q1      500   ║
║ Bill   Q2      520   ║
║ Bill   Q3      550   ║
║ Bob    Q2      200   ║
║ Bob    Q3      250   ║
╚══════════════════════╝

Мне нужно повернуть ее в формате, указанном ниже. Здесь каждое отдельное значение квартала становится столбцом, а каждый квартальный объем продаж является значением соответствующего столбца для каждого продавца.

╔══════════════════════╗
║ Name   Q1   Q2   Q3  ║
╠══════════════════════╣
║ Joe    700  650  660 ║
║ Bill   500  520  550 ║
║ Bob         200  250 ║
╚══════════════════════╝

Возможно ли это с SQL? Я использую SQL Сервер, но предпочитаю простой SQL, если возможно.

Мы не знаем значений, которые go в столбце Квартал впереди, т.е. мы не ограничены только Q1 / Q2 / Q3 et c. Допустим, пользователи могут войти в Q1, Quarter 1 или что-то еще, что им нравится.

Ответы [ 2 ]

3 голосов
/ 14 февраля 2020

Я бы предложил вместо этого использовать метод PIVOT.

Посмотрев на комментарий выше, вы сделали wi sh, чтобы сделать квартал Q1, Q2 ... динамическим, как вы могли бы этого не делать. есть конкретные c значения для Quarter.

Здесь я обновил свой ответ, пожалуйста попробуйте и посмотрите.

Замените PivotSample на вас TableName

IF OBJECT_ID('tempdb..##TEMP_TBL') IS NOT NULL
DROP TABLE ##TEMP_TBL

--GET all pivoted column -> [Q1], [Q12]...
DECLARE @pivot_col AS NVARCHAR(MAX)
;WITH distinct_col AS
(
    SELECT DISTINCT [Quarter]
    FROM PivotSample
)
SELECT @pivot_col = COALESCE(@pivot_col + ',', '') + QUOTENAME([Quarter])
FROM distinct_col

--Generate query, to pivot the data given
DECLARE @query AS NVARCHAR(MAX)
SET @query = 
    N'SELECT [Name], ' + @pivot_col + ' ' +
    'INTO ##TEMP_TBL
    FROM PivotSample
    PIVOT
    (
        SUM(Sales)
        FOR [Quarter] IN ( ' + @pivot_col + ' )
    ) AS pvt'

--Execute query, to insert result into ##TEMP_TBL
EXEC sp_executesql @query


--GET all [Quarter] column, to add in ISNULL after PIVOT column -> e.g:  ISNULL([Q1], 0) AS [Q1], ISNULL([Q2], 0) AS [Q2]...
DECLARE @col_name AS NVARCHAR(MAX)
;WITH distinct_col AS
(
    SELECT DISTINCT [Quarter]
    FROM PivotSample
)
SELECT @col_name =
        STUFF(
        (
            SELECT ', ISNULL(' + QUOTENAME([Quarter]) + ', 0) AS ' + QUOTENAME([Quarter])
            FROM distinct_col
            ORDER BY [Quarter]
            FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)')
        ,1 , 1, '')

--Generate query_result, to get result from ##TEMP_TBL after add in ISNULL
DECLARE @query_result AS NVARCHAR(MAX)
SET @query_result = 
    N'SELECT [Name], ' + @col_name + ' ' +
    'FROM ##TEMP_TBL
    ORDER BY [Name]'

--Execute query_result, final result shown
EXEC sp_executesql @query_result
2 голосов
/ 14 февраля 2020

Вы можете попробовать использовать условие агрегации SUM с CASE WHEN

SELECT Name,
       SUM(CASE WHEN Quarter = 'Q1' THEN Sales ELSE 0 END) 'Q1',
       SUM(CASE WHEN Quarter = 'Q2' THEN Sales ELSE 0 END) 'Q2',
       SUM(CASE WHEN Quarter = 'Q3' THEN Sales ELSE 0 END) 'Q3'
FROM T
GROUP BY Name
...