在sql查询中将行转换为列的正确方法

时间:2017-10-10 21:11:57

标签: sql-server tsql pivot

这是我的常规选择查询:

SELECT [category], [price], [company]
FROM [prices] 
INNER JOIN [company] AS [co] ON [co].[company] = [pr].[company]
WHERE [co].[id] IN (1,2,3);

结果是:

category | price | company 
---------+-------+-------------
 Srv     | 1200  | CoA
 Srv     | 2800  | CoB
 EQ      | 5400  | CoA
 Deduc   | 400   | CoA
 Deduc   | 150   | CoB   

我需要这个结果:

PriceASrv  | PriceBSrv | PriceAEQ | PriceBEQ | PriceADeduc | PriceBDeduc
-----------+-----------+----------+----------+-------------+-------------
 1200      | 2800      | 5400     | NULL     | 400         | 150

看来我需要两次PIVOT,对吗?有没有人有任何想法?

2 个答案:

答案 0 :(得分:1)

不,您不需要两次转动,但在以下情况下您可能需要动态查询:

  1. 可以有两家以上的公司,或者
  2. 您的公司名称可以更改,或者
  3. 您的类别可能会发生变化
  4. 如果这三个条件都是假的,则以下任一查询都可以起作用:

    DECLARE @T TABLE (Category VARCHAR(10), Price INT, Company CHAR(3));
    INSERT @T VALUES
        ('Srv', 1200, 'CoA'),
        ('Srv', 2800, 'CoB'),
        ('EQ', 5400, 'CoA'),
        ('Deduc', 400, 'CoA'),
        ('Deduc', 150, 'CoB');
    
    -- With PIVOT
    SELECT *
    FROM (
        SELECT CatCom = 'Price' + RIGHT(Company, 1) + Category,
               Price 
        FROM @T) AS T
    PIVOT (MAX(Price) FOR CatCom IN ([PriceASrv], [PriceBSrv], [PriceAEQ], [PriceBEQ], [PriceADeduc], [PriceBDeduc])) AS P
    
    -- With CASE aggregation
    SELECT PriceASrv = MAX(CASE WHEN Category = 'Srv' AND Company = 'CoA' THEN Price END),
           PriceBSrv = MAX(CASE WHEN Category = 'Srv' AND Company = 'CoB' THEN Price END),
           PriceAEQ = MAX(CASE WHEN Category = 'EQ' AND Company = 'CoA' THEN Price END),
           PriceBEQ = MAX(CASE WHEN Category = 'EQ' AND Company = 'CoB' THEN Price END),
           PriceADeduc = MAX(CASE WHEN Category = 'Deduc' AND Company = 'CoA' THEN Price END),
           PriceBDeduc = MAX(CASE WHEN Category = 'Deduc' AND Company = 'CoB' THEN Price END)
    FROM @T;
    

    如果这三个条件中的任何一个都是真的,那么您可能需要一个动态查询(基本上可以修改上述任一查询以满足您的需求)。

答案 1 :(得分:1)

不,你不需要两次PIVOT。见下面的查询。如果您不知道可能存在的公司数量,您可以转换为动态支点

Select * from 
(
Select 
  [data]='Price' + RIGHT([company],1) +[category] , 
  [price]
FROM [prices] 
INNER JOIN [company] as [co] On [co].[company] = [pr].[company]
WHERE [co].[id] In (1,2,3))src
PIVOT
( 
MAX([price]) FOR [data] in (PriceASrv,PriceBSrv,PriceAEQ,PriceBEQ,PriceADeduc,PriceBDeduc)
)p

<强> see working demo