在 ms sql 中旋转 2 列并依次显示数据
Posted
技术标签:
【中文标题】在 ms sql 中旋转 2 列并依次显示数据【英文标题】:pivot 2 columns and show data one after another in ms sql 【发布时间】:2018-02-14 23:06:20 【问题描述】:下面是我的桌子
我想要的结果如下
通过枢轴我实现了如下
这个但仍然需要一个接一个的列。
下面是我写的查询
DECLARE @pivot1 varchar(8000), DECLARE @pivot2 varchar(8000)
SELECT @pivot1=coalesce(@pivot1+',','')+'[cust'+cast(number+1 as varchar(10))+']' FROM master..spt_values where type='p' and number<=(SELECT max(len(cust1)-len(replace(cust1,',',''))) FROM xyz1)
SELECT @pivot2=coalesce(@pivot2+',','')+'[city'+cast(number+1 as varchar(10))+']' FROM master..spt_values where type='p' and number<=(SELECT max(len(city1)-len(replace(city1,',',''))) FROM xyz1)
SELECT A.*, B.* FROM (
select p.*
from (
select
product,substring(cust, start+2, endPos-Start-2) as token,
'cust'+cast(row_number() over(partition by product order by start) as varchar(10)) as n
from (
select
product, Customer, n as start, charindex(',',Customer,n+2) endPos
from (select number as n from master..spt_values where type='p') num
cross join
(
select product, ',' + Customer +',' as cust
from
xyz1
) m
where n < len(cust)-1
and substring(cust,n+1,1) = ',') as cust
) pvt
Pivot ( max(token)for n in ([cust1],[cust2],[cust3]))p ) A JOIN (
select
product,substring(city, start+2, endPos-Start-2) as token,
'city'+cast(row_number() over(partition by product order by start) as varchar(10)) as n
from (
select
product, Customer, n as start, charindex(',',Customer,n+2) endPos
from (select number as n from master..spt_values where type='p') num
cross join
(
select product, ',' + City +',' as city
from
xyz1
) m
where n < len(city)-1
and substring(city,n+1,1) = ',') as city
) pvt
Pivot ( max(token)for n in ([city1],[city2],[city3]))p ) B
ON A.product = B.product
xyz & xyz1 如下图:
xyz 视图:-
SET ANSI_NULLS ON GO
SET QUOTED_IDENTIFIER ON GO
ALTER view [dbo].[xyz] as select product, Customer, City from Customer with (nolock) where product IN (1,2)
GO
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO
和 xyz1 视图为:
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO
ALTER view [dbo].[xyz1] as
SELECT product, Customer, City ,Customer1=STUFF (
(
SELECT ', '+ CAST(sh.Customer AS VARCHAR(MAX))
FROM xyz sh
where sh.product IN (1,2)
FOR XMl PATH('')
),1,1,''
) ,City=STUFF (
(
SELECT ', '+ CAST(sh.City AS VARCHAR(MAX))
FROM xyz sh
where sh.product IN (1,2)
FOR XMl PATH('')
),1,1,''
) FROM xyz t1 where t1.product IN (1,2)
GO
【问题讨论】:
随心所欲选择列..顺序无关紧要 我无法在 SELECT 子句中指定列名,因为列名是在我 PIVOT 时动态生成的。 你能显示你的代码吗? 我已经更新了@Nithin 的问题 视图在哪里? xyz 和 xyz1 【参考方案1】:这些列按照您在 SELECT 列表中指定的顺序出现。
如有必要,将您当前的查询转换为 CTE 或派生表,并从中按您想要的顺序使用列执行外部 SELECT。
【讨论】:
我无法在 SELECT 子句中指定列名,因为列名是在我 PIVOT 时动态生成的。 是的,你可以,你只需要动态生成 SELECT 子句,就像动态生成 PIVOT 一样。【参考方案2】:尝试使用 cte(common table expression) 选择表
;with cte as (SELECT A.*, B.* FROM (
select p.*
from (
select
product,substring(cust, start+2, endPos-Start-2) as token,
'cust'+cast(row_number() over(partition by product order by start) as varchar(10)) as n
from (
select
product, Customer, n as start, charindex(',',Customer,n+2) endPos
from (select number as n from master..spt_values where type='p') num
cross join
(
select product, ',' + Customer +',' as cust
from
xyz1
) m
where n < len(cust)-1
and substring(cust,n+1,1) = ',') as cust
) pvt
Pivot ( max(token)for n in ([cust1],[cust2],[cust3]))p ) A JOIN (
select
product,substring(city, start+2, endPos-Start-2) as token,
'city'+cast(row_number() over(partition by product order by start) as varchar(10)) as n
from (
select
product, Customer, n as start, charindex(',',Customer,n+2) endPos
from (select number as n from master..spt_values where type='p') num
cross join
(
select product, ',' + City +',' as city
from
xyz1
) m
where n < len(city)-1
and substring(city,n+1,1) = ',') as city
) pvt
Pivot ( max(token)for n in ([city1],[city2],[city3]))p ) B
ON A.product = B.product)
select product,cust1,city1,cust2,city2,cust3,city3 from cte;
【讨论】:
如果我的数据不同,它会起作用吗,比如 cust 和 city 可能会有所不同,max 可以是 10,min 可以是 1。以上是关于在 ms sql 中旋转 2 列并依次显示数据的主要内容,如果未能解决你的问题,请参考以下文章
如何使 Excel 在 MS SQL 2017 中任意旋转(交叉连接 + 循环)
如何保持某些列原样并动态旋转 SQL Server 2012 中的最后一列 [重复]