使用动态SQL将两列连接到具有各自值的表头中 [英] Using dynamic SQL to concatenate two columns into a table header with their respective values

查看:84
本文介绍了使用动态SQL将两列连接到具有各自值的表头中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个表,GuestList和CustomerList。我加入了它们并使用动态SQL数据透视表将GuestList表中的city列转换为行或表标题,并在每个城市下显示平均人口。因此,在底部执行查询后,我的表头看起来像这样,每个城市下面都会显示平均人口数。



时间|亚特兰大|洛杉矶|纽约|丹佛|明尼阿波利斯



但我希望我的表头看起来像这样。基本上'Id'有四个值,1,2,3,4,每个城市都有这四个ID。我无法添加所有城市,但其他城市也将如此。



时间| Atlanta_1 || Atlanta_2 || Atlanta_3 || Atlanta_4 |



有人可以通过编写剩下的查询来帮助我解决如何连接GuestList表中的两列并将它们各自的人口放在它下面的问题。



我的尝试:



I have a two tables, GuestList and CustomerList. I joined them and used dynamic SQL pivot table to convert the 'city' column from GuestList table into rows or table headers and the average population would be displayed under each city. So after executing the query at the bottom, my table header looks like this and the average population is displayed under each city.

Time| Atlanta| Los Angeles | New York | Denver| Minneapolis

But I want my table header to look like this. Basically 'Id' has four values, 1, 2,3,4 and each city has all these four ID's. I could not add all the cities but rest of the cities will also be like this.

Time| Atlanta_1|| Atlanta_2|| Atlanta_3|| Atlanta_4|

Could someone help me on this by writing the rest of the query on how to concatenate the two columns in the GuestList table and put their respective population underneath it.

What I have tried:

declare @ColumnNames nvarchar(max) = ''
declare @SQL nvarchar(max) = ''

select @ColumnNames += QUOTENAME(a.address) + ','
from GuestList as a
inner join CustomerList as b
on a.Id = b.Id
group by a.address
order by a.address 

set @ColumnNames = left(@ColumnNames, LEN(@ColumnNames)-1  )

set @SQL= N'
select Time,' + @ColumnNames + '
from 
(
select a.Time, a.city, a.population, b.Gender
from GuestList as a
inner join CustomerList as b
on a.Id = b.Id
inner join Split(@city, '','') as c
on a.city = c.Data
where a.city = c.Data
) as SourceTable
pivot
(avg(population) 
for city 
in (' 
    + @ColumnNames + 
    ')) as PivotTable
order by Time'


execute sp_executesql @SQL,
                        N'@city nvarchar(max)'
                        ,@city = 'Atlanta,Los Angeles,New York'

推荐答案

这个SQL有一些问题,因为它代表...避免使用保留字作为列名,或者如果你这样做,你应该用[] - [时间] 和 [人口] 在这种情况下。



该代码读取的片段...
You have some issues with this SQL as it stands ... avoid using reserved words as column names, or if you do then you should surround them with [ ] - [Time] and [Population] in this case.

That code snippet that reads ...
inner join Split(@city, '','') as c
on a.city = c.Data
where a.city = c.Data

WHERE 子句只是重复什么 ON 条款是这样说的,这是毫无意义的。因为你实际上并没有使用 CustomerList 中的任何内容,所以 JOIN 本身就是多余的。



要使用ID作为后缀获取列名,可以执行以下操作(更改带下划线):

the WHERE clause is just repeating what the ON clause is saying so it's pointless. Even more so as you are not actually using anything from CustomerList so the JOIN itself is redundant.

To get your column names with the ID as a suffix you can do the following (changes underlined):

select @ColumnNames += QUOTENAME(city + idcol) + ','
from #GuestList 
cross join (select '_' + cast(id as varchar) as idcol from #GuestList Group by Id) cx
group by city, idcol
order by city, idcol 

,它提供

[Atlanta_1],[Atlanta_2],[Atlanta_3],[Atlanta_4],[Denver_1],[Denver_2],[Denver_3],[Denver_4], etc ...

如果插入(注意我)已经使用了临时表并摆脱了多余的东西)

If you plug that in (note I've used temp tables and got rid of redundant stuff)

set @SQL= N'

select Time,' + @ColumnNames + '
from 
(
	select [Time], city, population, id, city + ''_'' + cast(Id as varchar) as cityWithId	from #GuestList
) as SourceTable
pivot
(avg(population) 
for cityWithId
in (' 
    + @ColumnNames + 
    ')) as PivotTable
group by [Time], ' + @ColumnNames + 
' order by [Time]'

你不幸得到这样的东西....

you unfortunately get stuff like this....

08:00:00	NULL	NULL	NULL	NULL	NULL	NULL	NULL	210
08:00:00	NULL	NULL	NULL	NULL	NULL	NULL	220	NULL
08:00:00	NULL	NULL	NULL	NULL	NULL	210	NULL	NULL
08:00:00	NULL	NULL	NULL	NULL	200	NULL	NULL	NULL
08:00:00	NULL	NULL	NULL	130	NULL	NULL	NULL	NULL
08:00:00	NULL	NULL	140	NULL	NULL	NULL	NULL	NULL
08:00:00	NULL	130	NULL	NULL	NULL	NULL	NULL	NULL
08:00:00	120	NULL	NULL	NULL	NULL	NULL	NULL	NULL

但您可以通过将整个事物包装在CTE中并计算这些列的MAX来处理...首先:

But you can handle that by wrapping the whole thing in a CTE and calculating the MAX of those columns...first:

declare @ColumnNames2 nvarchar(max) = ''
select @ColumnNames2 += 'MAX('+QUOTENAME(a.city + idcol) + ') as ' + QUOTENAME(a.city + idcol) +','
from #GuestList as a
cross join (select '_' + cast(id as varchar) as idcol from #GuestList Group by Id) cx
group by a.city, idcol
order by a.city 
set @ColumnNames2 = left(@ColumnNames2, LEN(@ColumnNames2)-1  )

将结果

MAX([Atlanta_1]) as [Atlanta_1],MAX([Atlanta_2]) as [Atlanta_2],MAX([Atlanta_3]) as [Atlanta_3],MAX([Atlanta_4]) as [Atlanta_4], etc...

然后动态sql构建看起来像这样(请注意的订单已移动!)

then the dynamic sql build looks like this (note the order by has moved!)

set @SQL= N'
;with CTE AS (
select Time,' + @ColumnNames + '
from 
(
	select [Time], city, population, id, city + ''_'' + cast(Id as varchar) as cityWithId
	from #GuestList
) as SourceTable
pivot
(avg(population) 
for cityWithId
in (' 
    + @ColumnNames + 
    ')) as PivotTable
group by [Time], ' + @ColumnNames + 
') select [Time], ' + @ColumnNames2 + ' from CTE GROUP BY [Time]
 order by [Time]'



不漂亮,但似乎有效


Not pretty but it seems to work


这篇关于使用动态SQL将两列连接到具有各自值的表头中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆