table 的动态列

Dynamic columns for table

我有 table 销售额:

SalesID. Date. Geography

1.       2020-01.  Italy
1.       2020-01.  France
1.       2020-01.  UK
2.       2020-02.  Italy
2.       2002-02.  Canada
3.       2002-08.  France

我想要这样的结果:

SalesID. Date. Geography1 Geography2.    Geography3
1.    2020-01.   Italy. France. Uk
2.  2020-02.  Italy.  Canada.  Null
3. 2020-08. France

我知道如何对列进行透视,但销售 ID 的地理数量不受限制。如何做到这一点?

CREATE TABLE MyTable(
SalesID INT,
[Date] varchar(20),
Geography VARCHAR(50)
);
INSERT INTO MyTable(SalesID,[Date],Geography)VALUES
(1,'2020-01','Italy'),(1,'2020-01','France'),
(1,'2020-01','UK'),(2,'2020-02','Italy'),(2,'2020-02','Canada'),
(3,'2020-08','France');


DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(a.Geography) 
            FROM MyTable a
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT date, ' + @cols + ' from 
            (
                select 
                    SalesID
                    ,Date
                    , Geography
                
                from MyTable
           ) x
            pivot 
            (
                 max(Geography)
                for Geography in (' + @cols + ')
            ) p '


execute(@query)
date    | Canada | France | Italy | UK  
:------ | :----- | :----- | :---- | :---
2020-01 | null   | France | Italy | UK  
2020-02 | Canada | null   | Italy | null
2020-08 | null   | France | null  | null

db<>fiddle here

;WITH L AS(
SELECT SalesID, Date, Geography
from
(
SELECT 1 as SalesID,       '2020-01' as Date,  'Italy' as Geography
UNION ALL
SELECT 1,       '2020-01',  'France'
UNION ALL
SELECT 1,       '2020-01',  'UK'
UNION ALL
SELECT 2,       '2020-02',  'Italy'
UNION ALL
SELECT 2,       '2020-02',  'Canada'
UNION ALL
SELECT 3,       '2002-08',  'France'
)S
),

L1 AS(
SELECT SalesID, Date, Geography
from
(
SELECT 1 as SalesID,       '2020-01' as Date,  'Italy' as Geography
UNION ALL
SELECT 1,       '2020-01',  'France'
UNION ALL
SELECT 1,       '2020-01',  'UK'
UNION ALL
SELECT 2,       '2020-02',  'Italy'
UNION ALL
SELECT 2,       '2020-02',  'Canada'
UNION ALL
SELECT 3,       '2002-08',  'France'
)S
)


SELECT
   L.SalesID,L.Date,
   STUFF((SELECT '; ' + L1.Geography
          FROM L1
          WHERE L1.SalesID = L.SalesID
 AND L1.Date = L.Date
          FOR XML PATH('')), 1, 1, '') [Geography]
FROM L
GROUP BY L.SalesID, L.Date
ORDER BY 1

这里是 SQL 查询的输出截图: