【问题标题】:SQL Server pivot text valuesSQL Server 透视文本值
【发布时间】:2020-03-11 00:18:58
【问题描述】:

我正在练习枢轴。我有一个包含姓名和职业数据的表格(生成示例的代码如下)。我需要将职业放在列中,并在每个职业、名称下方堆叠。 Null 很好。

我看过很多帖子,this 一个是我需要的,但是一旦适应了我的数据,它只拉取 1 行数据。

这里是生成示例和实际数据透视代码的代码。我该如何纠正这个错误?

declare @occupations table (ename nvarchar(10), occupation nvarchar(10) )
insert @occupations
values 
('John','Doctor'),('Mary','Doctor'),('Jack','Doctor'),('Anna','Doctor'),
('Jim','Singer'),('Kate','Singer'),('Helen','Actor'),('Paco','Singer')

SELECT [Doctor] Doctor, [Singer] Singer, [Actor] Actor
FROM @occupations
PIVOT
  (min(ename)  
    FOR occupation IN ([Doctor],[Singer], [Actor])  
  )AS pp

我得到这个结果:

 Doctor Singer Actor
 Anna   Jim    Helen    

应该有更多行来包含所有名称。 IE。例如,您可以在插入语句中看到有 4 位医生。所以应该是带有一些空值的 8 行。

【问题讨论】:

  • 职业是否包含除医生、歌手、演员以外的其他价值观?
  • 这能回答你的问题吗? how to make your data horizontal
  • @xXx,不,那个帖子没有回答,它有点不同,我实际上需要了解为什么我的代码不起作用,所以从那个帖子我无法想办法。不过,谢谢您的帮助。

标签: sql-server pivot


【解决方案1】:

如果您想要所有行,只需添加一个唯一键,如 row_number()

示例

SELECT [Doctor] Doctor, [Singer] Singer, [Actor] Actor
FROM (
       Select *
             ,rn=row_number() over(order by ename) 
        from @occupations
     ) src
PIVOT
  (min(ename)  
    FOR occupation IN ([Doctor],[Singer], [Actor])  
  )AS pp

退货

Doctor  Singer  Actor
Anna    NULL    NULL
NULL    NULL    Helen
Jack    NULL    NULL
NULL    Jim     NULL
John    NULL    NULL
NULL    Kate    NULL
Mary    NULL    NULL
NULL    Paco    NULL

【讨论】:

  • 谢谢,解决了。希望我也知道为什么 - 是因为 MIN 是一个聚合函数吗?
  • @LanaB 很高兴为您提供帮助,PIVOT 默认情况下是一个聚合,因此“喂”它一个独特的聚合键只是一件小事。在这种情况下 row_number()
【解决方案2】:

您还可以使其动态自动选择所有列

create table #occupations  (ename nvarchar(10), occupation nvarchar(10) )
insert   #occupations
values 
('John','Doctor'),('Mary','Doctor'),('Jack','Doctor'),('Anna','Doctor'),
('Jim','Singer'),('Kate','Singer'),('Helen','Actor'),('Paco','Singer') ;


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

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

set @query = 'SELECT * FROM #occupations
                    PIVOT
                        (min(ename)  
                FOR occupation IN ('+ @cols +')  
              )AS pp'
exec (@query) 
drop table #occupations

【讨论】:

    【解决方案3】:

    SQL Fiddle Execution

    MS SQL Server 2017 架构设置

    create table occupations (ename nvarchar(10), occupation nvarchar(10) )
    insert into occupations(ename,occupation)values ('John','Doctor'),('Mary','Doctor'),('Jack','Doctor'),('Anna','Doctor'),
    ('Jim','Singer'),('Kate','Singer'),('Helen','Actor'),('Paco','Singer')
    

    **查询**:

    WITH CTE AS (
      SELECT *,
      (case when occupation like 'singer' then ename end) AS Singer,
        (case when occupation like 'doctor' then ename end) AS Doctor,
        (case when occupation like 'Actor' then ename end) AS Actor,
      ROW_Number() OVER (PARTITION BY occupation Order By ename) as rn
      from occupations
      group by ename,occupation)
    
      select max(Singer) AS Singer,max(Doctor) AS Doctor, max(Actor) AS Actor
      from cte
      where rn=1 
    

    Results

    | Singer | Doctor | Actor |
    |--------|--------|-------|
    |    Jim |   Anna | Helen |
    

    【讨论】:

    • 你的查询结果是我得到的,问题是获取所有行,上面的帖子解决了它。感谢您的帮助,您的查询仍然很有帮助,我一定会了解它的作用。
    猜你喜欢
    • 1970-01-01
    • 2015-10-26
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多