我正在尝试查找可以动态生成多个级别的交叉表输出的查询。我确实在网上找到了一些返回动态交叉表结果的解决方案,但它只返回单一级别。下面是SQL小提琴:
CREATE TABLE dbo.PopulationDetails
(
Country VARCHAR(50),
State VARCHAR(50),
Population BIGINT,
SeatsInHouse INT
)
INSERT INTO PopulationDetails
VALUES('United States','California', 38332521, 53),
('United States','Texas', 26448193, 36),
('United States','New York', 19651127, 27),
('United States','Florida', 19552860, 27),
('United States','Illinois', 12882135, 18)
我希望我的输出看起来如下所示。状态数量不固定,可能会根据要求而有所不同。
United States
California Texas New York Florida Illinois
Population 38332521 26448193 19651127 19552860 12882135
SeatsInHouse 53 36 27 27 18
答案 0 :(得分:3)
正如我在评论中所说,多级列标题不能通过SQL完成。您必须在表单层格式化数据,如应用程序或SSRS。如果您希望同时获得country
和state
值",那么您必须将这些名称连接在一起并将其设为新的列名。
如果您想在SQL中获得结果,我首先要联接country
和state
以及unpivot
列population
和{{ 1}}首先。此过程的基本语法是:
SeatsInHouse
见SQL Fiddle with Demo。这给出了一个结果:
select
country_state = replace(pd.Country +'_'+pd.State, ' ', ''),
c.col,
c.value
from dbo.PopulationDetails pd
cross apply
(
values
('Population', pd.population),
('SeatsInHouse', pd.SeatsInHouse)
) c (col, value);
您会看到每个| COUNTRY_STATE | COL | VALUE |
|-------------------------|--------------|----------|
| UnitedStates_California | Population | 38332521 |
| UnitedStates_California | SeatsInHouse | 53 |
| UnitedStates_Texas | Population | 26448193 |
| UnitedStates_Texas | SeatsInHouse | 36 |
| UnitedStates_NewYork | Population | 19651127 |
| UnitedStates_NewYork | SeatsInHouse | 27 |
组合现在有两行。您现在可以将这些Country_State
值转换为列:
Country_State
现在,如果您需要动态完成此操作,那么您必须使用动态SQL创建一个然后执行的字符串。
select col, UnitedStates_California, UnitedStates_Texas,
UnitedStates_NewYork, UnitedStates_Florida,
UnitedStates_Illinois
from
(
select
country_state = replace(pd.Country +'_'+pd.State, ' ', ''),
c.col,
c.value
from dbo.PopulationDetails pd
cross apply
(
values
('Population', pd.population),
('SeatsInHouse', pd.SeatsInHouse)
) c (col, value)
) d
pivot
(
max(value)
for country_state in (UnitedStates_California, UnitedStates_Texas,
UnitedStates_NewYork, UnitedStates_Florida,
UnitedStates_Illinois)
) piv;
见SQL Fiddle with Demo。两者都给出了结果:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(country_state)
from
(
select country_state = replace(Country +'_'+State, ' ', '')
from dbo.PopulationDetails
) d
group by country_state
order by country_state
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT col, ' + @cols + '
from
(
select
country_state = replace(pd.Country +''_''+pd.State, '' '', ''''),
c.col,
c.value
from dbo.PopulationDetails pd
cross apply
(
values
(''Population'', pd.population),
(''SeatsInHouse'', pd.SeatsInHouse)
) c (col, value)
) x
pivot
(
max(value)
for country_state in (' + @cols + ')
) p '
exec sp_executesql @query;