SQL Server 2008:需要“转置”结果集

时间:2014-02-13 12:25:50

标签: sql sql-server-2008

我在创建查询时遇到问题。我有以下表格(简化):

表1

doc_no         line         country
12             1            NL
12             2            US
12             ...          ...
12             m            FR
13             1            NL
13             ...          ...
13             n            GR 
...            ...          ...

表2

doc_no         user_doc
12             123456
13             654321

我需要创建一个连接doc_no上的两个表并返回以下结果集的查询:

user_doc       country-1     country-2    country-...    country-m
123456         NL            US           ...            FR

user_doc       country-1     country-...  country-n
654321         NL            ...          GR

user_doc       country-...
...            ...

两个表中没有m,n或doc_no数量的设定值。最后,结果集将被限制为查询运行的时间间隔(可能是30或60秒),因此结果集可以是doc_no的10。最有可能的是结果集的范围是1到5个user_doc,但可能更多。

数据库只允许数据提取,所以我不能使用T-SQL创建临时表,存储过程,视图等只使用局部变量等的select-type查询。

我完全迷失了解决方案,所以任何建议都会很精彩

THX,

马丁

1 个答案:

答案 0 :(得分:0)

这可以通过修改@Bluefeet的dynamic pivot strategy并使用动态Sql来完成。我假设'Country-X'标题使用列line的值为x

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

-- Grab the distinct Lines to use as column headings 
-- (This is a `GROUP_CONCAT` workaround)
SET @pivotCols = STUFF((SELECT distinct ',' + 
       QUOTENAME('Country-' + CAST(Line AS NVARCHAR(20))) 
            FROM table1
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'');

set @query = '
    SELECT user_doc, ' + @pivotCols + '
    FROM
    (
        select ''Country-''+CAST(t1.Line AS NVARCHAR(20)) AS Line,  
                    t1.Country, t2.user_doc
        from table1 t1
            inner join table2 t2 on t1.doc_no = t2.doc_no
     ) x
     pivot 
    (
       MIN(Country)
       for Line in (' + @pivotCols + ')
    ) p';

execute(@query);

如果每个doc_no + line组合有多个国家/地区,则会选择最低国家/地区。如果没有这样的行,则显示空值。

SqlFiddle here

修改

以下使用ROW_NUMBER()添加任意计数器,而不是依赖Line(根据需要更改ORDER BY)。我使用了一个令人讨厌的#temp表hack(因为EXEC'ed查询也可以访问#Temp表)来干掉列的命名。

DECLARE 
  @pivotCols AS NVARCHAR(MAX),
  @aliasCols AS NVARCHAR(MAX),
  @query  AS NVARCHAR(MAX);

select 'Country-'+CAST(y.TheNumber AS NVARCHAR(20)) AS ColName, 
           y.Country,
           y.user_doc
    into #temp
    from 
    ( 
        SELECT 
           t1.Country, t2.user_doc, 
           ROW_NUMBER() OVER (PARTITION BY t1.doc_no ORDER BY LINE ASC) AS TheNumber
        FROM 
           table1 t1
           inner join table2 t2 on t1.doc_no = t2.doc_no
     ) y;

SET @pivotCols = STUFF((SELECT distinct ',' + QUOTENAME(ColName)
            FROM #temp
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'');

set @query = '
    SELECT user_doc, ' + @pivotCols + '
    FROM
    #temp x
    pivot 
    (
       MIN(Country)
       for ColName in (' + @pivotCols + ')
    ) p';

execute(@query);

Updated SqlFiddle here