我在创建查询时遇到问题。我有以下表格(简化):
表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,
马丁
答案 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
组合有多个国家/地区,则会选择最低国家/地区。如果没有这样的行,则显示空值。
修改强>
以下使用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);