Câu hỏi SQL Server - PIVOT - hai cột thành hàng


Tôi thấy nhiều câu hỏi về PIVOT cho một cột duy nhất, mỗi câu hỏi phức tạp hơn câu hỏi khác, tuy nhiên, tôi không thể tìm thấy bất cứ điều gì giống như những gì tôi cần.

Thành thật mà nói, tôi thậm chí không biết liệu trục xoay có giúp tôi trong tình huống này hay không.

Giả sử tôi có dữ liệu này trên bảng nguồn của mình:

SELECT '1' as 'RowId', 'RandomName1' as 'First', 'RandomLast1' as 'Last'
UNION
SELECT '2' as 'RowId', 'RandomName2' as 'First', 'RandomLast2' as 'Last'
UNION
SELECT '3' as 'RowId', 'RandomName3' as 'First', 'RandomLast3' as 'Last'
UNION
SELECT '4' as 'RowId', 'RandomName4' as 'First', 'RandomLast4' as 'Last'
UNION
SELECT '5' as 'RowId', 'RandomName5' as 'First', 'RandomLast5' as 'Last'

Tối đa 5 hàng có tên và họ. Giá trị của các cột Đầu tiên và Cuối cùng sẽ là ngẫu nhiên.

RowId First       Last
----- ----------- -----------
1     RandomName1 RandomLast1
2     RandomName2 RandomLast2
3     RandomName3 RandomLast3
4     RandomName4 RandomLast4
5     RandomName5 RandomLast5

Tôi đã cố gắng xoay dữ liệu này thành một thứ như thế này:

First1      Last1       First2      Last2       First3      Last3       First4      Last4       First5      Last5
----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
RandomName1 RandomLast1 RandomName2 RandomLast2 RandomName3 RandomLast3 RandomName4 RandomLast4 RandomName5 RandomLast5

Ví dụ: Tôi không có bất kỳ vấn đề nếu cột First5 và Last5 là NULL vì chỉ có 4 hàng.

First1      Last1       First2      Last2       First3      Last3       First4      Last4       First5      Last5
----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
RandomName1 RandomLast1 RandomName2 RandomLast2 RandomName3 RandomLast3 RandomName4 RandomLast4 NULL        NULL

Bất cứ ai có thể cho tôi một chút giúp đỡ? Cảm ơn.


Giải pháp dựa trên câu trả lời của Sheela K R:

SELECT 
    MAX(First1) as 'First1',  MAX(Last1) as 'Last1',
    MAX(First2) as 'First2',  MAX(Last2) as 'Last2',
    MAX(First3) as 'First3',  MAX(Last3) as 'Last3',
    MAX(First4) as 'First4',  MAX(Last4) as 'Last4',
    MAX(First5) as 'First5',  MAX(Last5) as 'Last5'
FROM
(
    SELECT 
        CASE WHEN RowId = 1 THEN [First] END as 'First1',
        CASE WHEN RowId = 1 THEN [Last] END as 'Last1',
        CASE WHEN RowId = 2 THEN [First] END as 'First2',
        CASE WHEN RowId = 2 THEN [Last] END as 'Last2',
        CASE WHEN RowId = 3 THEN [First] END as 'First3',
        CASE WHEN RowId = 3 THEN [Last] END as 'Last3',
        CASE WHEN RowId = 4 THEN [First] END as 'First4',
        CASE WHEN RowId = 4 THEN [Last] END as 'Last4',
        CASE WHEN RowId = 5 THEN [First] END as 'First5',
        CASE WHEN RowId = 5 THEN [Last] END as 'Last5'
    FROM
    (
        SELECT '1' as 'RowId', 'RandomName1' as 'First', 'RandomLast1' as 'Last'
        UNION SELECT '2' as 'RowId', 'RandomName2' as 'First', 'RandomLast2' as 'Last'
        UNION SELECT '3' as 'RowId', 'RandomName3' as 'First', 'RandomLast3' as 'Last'
        UNION SELECT '4' as 'RowId', 'RandomName4' as 'First', 'RandomLast4' as 'Last'
        --UNION SELECT '5' as 'RowId', 'RandomName5' as 'First', 'RandomLast5' as 'Last'
    ) test
) test2

8
2018-01-21 06:20


gốc




Các câu trả lời:


Có một vài cách khác nhau để bạn có thể nhận được kết quả mà bạn muốn. Tương tự như @Sheela K R câu trả lời bạn có thể sử dụng một hàm tổng hợp với một biểu thức CASE nhưng nó có thể được viết theo một cách súc tích hơn:

select 
  max(case when rowid = 1 then first end) First1,
  max(case when rowid = 1 then last end) Last1,
  max(case when rowid = 2 then first end) First2,
  max(case when rowid = 2 then last end) Last2,
  max(case when rowid = 3 then first end) First3,
  max(case when rowid = 3 then last end) Last3,
  max(case when rowid = 4 then first end) First4,
  max(case when rowid = 4 then last end) Last4,
  max(case when rowid = 5 then first end) First5,
  max(case when rowid = 5 then last end) Last5
from yourtable;

Xem SQL Fiddle với bản trình diễn.

Điều này cũng có thể được viết bằng cách sử dụng hàm PIVOT, tuy nhiên vì bạn muốn xoay quanh nhiều cột thì trước tiên bạn sẽ muốn xem xét việc bỏ cấm First và Last cột.

Quá trình hủy hợp nhất sẽ chuyển đổi nhiều cột của bạn thành nhiều hàng dữ liệu. Bạn không chỉ định phiên bản SQL Server nào bạn đang sử dụng nhưng bạn có thể sử dụng SELECT với UNION ALL với CROSS APPLY hoặc thậm chí UNPIVOT để thực hiện chuyển đổi đầu tiên:

select col = col + cast(rowid as varchar(10)), value
from yourtable
cross apply 
(
  select 'First', First union all
  select 'Last', Last
) c (col, value)

Xem SQL Fiddle với bản trình diễn. Điều này chuyển đổi dữ liệu của bạn thành định dạng:

|    COL |       VALUE |
|--------|-------------|
| First1 | RandomName1 |
|  Last1 | RandomLast1 |
| First2 | RandomName2 |
|  Last2 | RandomLast2 |

Khi dữ liệu ở nhiều hàng, bạn có thể dễ dàng áp dụng hàm PIVOT:

select First1, Last1, 
  First2, Last2,
  First3, Last3, 
  First4, Last4, 
  First5, Last5
from
(
  select col = col + cast(rowid as varchar(10)), value
  from yourtable
  cross apply 
  (
    select 'First', First union all
    select 'Last', Last
  ) c (col, value)
) d
pivot
(
  max(value)
  for col in (First1, Last1, First2, Last2,
              First3, Last3, First4, Last4, First5, Last5)
) piv;

Xem SQL Fiddle với bản trình diễn

Cả hai đều cho kết quả:

|      FIRST1 |       LAST1 |      FIRST2 |       LAST2 |      FIRST3 |       LAST3 |      FIRST4 |       LAST4 |      FIRST5 |       LAST5 |
|-------------|-------------|-------------|-------------|-------------|-------------|-------------|-------------|-------------|-------------|
| RandomName1 | RandomLast1 | RandomName2 | RandomLast2 | RandomName3 | RandomLast3 | RandomName4 | RandomLast4 | RandomName5 | RandomLast5 |

10
2018-01-21 11:43



Bạn đóng đinh nó. Tôi thích cách súc tích, tôi đang sử dụng SQL 2012. - navossoc
@navossoc Cách súc tích chắc chắn dễ dàng hơn vì bạn có rowId có thể được sử dụng. - Taryn♦


Hãy thử một cái gì đó như thế này

CREATE TABLE #Table1
    ([uid] int, [name] varchar(4), [diseaseid] int, [intensity] varchar(4))
;

INSERT INTO #Table1
    ([uid], [name], [diseaseid], [intensity])
VALUES    (1, 'xxxx', 2, 'low')
    (1, 'xxxx', 1, 'high'),

;

SELECT MAX([uid]) AS [uid]
       ,MAX([name]) AS [name]
       ,MAX([diseaseid1]) AS [diseaseid1]
       ,MAX([intensity1]) AS [intensity1]
       ,MAX([diseaseid2]) AS [diseaseid2]
       ,MAX([intensity2]) [intensity2]
FROM 
(
    SELECT [uid], [name]
    , CASE WHEN rn=2 THEN NULL ELSE [diseaseid] END AS [diseaseid1]
    , CASE WHEN rn=2 THEN NULL ELSE [intensity] END AS [intensity1]
    , CASE WHEN rn=1 THEN NULL ELSE [diseaseid] END AS [diseaseid2]
    , CASE WHEN rn=1 THEN NULL ELSE [intensity] END AS [intensity2]
    FROM
    (
        SELECT [uid], [name], [diseaseid], [intensity], 
        ROW_NUMBER() OVER(PARTITION BY [uid] ORDER BY Name) AS rn
        FROM #Table1
    ) T
) T
GROUP BY [uid], [name]

2
2018-01-21 06:25



Không chính xác những gì tôi cần, nhưng câu trả lời của bạn đã giúp tôi rất nhiều để đạt được điều đó. Cảm ơn! - navossoc