Как использовать столбец строкового типа в SQL pivot - PullRequest
0 голосов
/ 02 декабря 2018

У меня есть таблица, подобная приведенной ниже

Name       Year       Bonus 
----      -----      ------
Ram       2011        1000
Ram       2011        2000
Shyam      2011       'No Bonus'
Shyam      2012       5000

Я хочу отобразить общий бонусный год для каждого человека. Я попытался выполнить запрос ниже

SELECT [Year],[Ram],[Shyam] FROM   
(SELECT Name, [Year] , Bonus FROM Employee )Tab1  
PIVOT  
(  
SUM(Bonus) FOR Name IN (Ram,Shyam)) AS Tab2  
ORDER BY [Tab2].[Year] 

Мой вывод должен быть таким, как показано ниже

Name      2011          2012
----      ------        ------
Ram        3000         0
Shyam     'No Bonus'    5000

Но это не работает.

Может кто-нибудь помочь мне в этом?

Ответы [ 3 ]

0 голосов
/ 02 декабря 2018

В соответствии с вашей проблемой, я понял следующий запрос.Не идеальное решение, но это подойдет.Вы можете изменить запрос, если вам нужно сделать его динамическим.

 SELECT [Name]
, case when [2011] = 0 then 'No Bonus' when [2011] is null then '0' else cast([2011] as varchar(50)) end as [2011]
, case when [2012] = 0 then 'No Bonus' when [2012] is null then '0' else cast([2012] as varchar(50)) end as [2012] 
FROM   
(SELECT Name, [Year] , cast(Bonus as int) Bonus FROM Employee)Tab1  
PIVOT  
(  
SUM(Bonus) FOR Year IN ([2011],[2012])) AS Tab2  
ORDER BY [Tab2].[Name] 

Вам нужно передать 0 в таблице, а затем изменить в PIVOT

0 голосов
/ 02 декабря 2018

Я бы просто отказался от хранения чисел в виде строк.Я не вижу разницы между 0 / NULL и 'No Bonus', за исключением того, что последний делает запросы склонными к действительно плохим проблемам преобразования типов.

Итак, мой совет:

SELECT [Year],[Ram],[Shyam]   
FROM (SELECT Name, [Year], TRY_CONVERT(int, Bonus) as Bonus
      FROM Employee
     ) e  
PIVOT (SUM(Bonus) FOR Name IN (Ram, Shyam)) AS Tab2  
ORDER BY [Tab2].[Year] ;

Возможно, вам не нравится это решение - хотя я действительно настоятельно рекомендую его, потому что я потратил слишком много времени на отладку проблем с числами и датами, хранящимися в виде строк.

Итак,если вы продолжаете хранить значения в виде строки, используйте условное агрегирование и набор логики:

select year,
       coalesce( sum(case when name = 'Ram'
                          then convert(varchar(255), try_convert(int, bonus))
                     end),
                 'No Bonus'
               ) as Ram,
       coalesce( sum(case when name = 'Shyam'                           
                          then convert(varchar(255), try_convert(int, bonus))
                     end),
                 'No Bonus'
               ) as Shyam    
from employee e
group by year
order by year;
0 голосов
/ 02 декабря 2018

Если ваша база данных является sql-сервером, вы можете попробовать использовать SUM функцию агрегирования условий в CTE

, затем используйте CAST с coalesce, чтобы сделать это.

;WITH CTE AS(
    SELECT Year,Name,
           SUM(CASE WHEN Bonus LIKE '%[0-9]%' THEN  CAST(Bonus AS DECIMAL) ELSE 0 END) total,
           COUNT(CASE WHEN Bonus = 'No Bonus' THEN 1 END) cnt
    FROM T 
    GROUP BY Year,Name
)
SELECT Name,
       coalesce(MAX(CASE WHEN  Year = 2011 THEN CAST(total AS VARCHAR(50)) END),'No Bonus') '2011',
       coalesce(MAX(CASE WHEN  Year = 2012 THEN CAST(total AS VARCHAR(50)) END),'No Bonus') '2012'
FROM CTE
GROUP BY Name

sqlfiddle

Если вы хотите динамически создавать столбцы, вы можете попробовать использовать динамический PIVOT.

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

;WITH CTE AS(
    SELECT Year,Name,
           SUM(CASE WHEN Bonus LIKE '%[0-9]%' THEN  CAST(Bonus AS DECIMAL) ELSE 0 END) total,
           COUNT(CASE WHEN Bonus = 'No Bonus' THEN 1 END) cnt
    FROM T 
    GROUP BY Year,Name
)
SELECT  @cols = STUFF((SELECT distinct ',coalesce(MAX(CASE WHEN cnt > 0 and Year = ' + cast(Year as varchar(5)) + ' THEN ''No Bonus''  WHEN Year = ' + cast(Year as varchar(5)) + ' and cnt = 0 THEN CAST(total AS VARCHAR(50)) END),''0'')' + QUOTENAME(Year)
            FROM CTE c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = '
;WITH CTE AS(
    SELECT Year,Name,
           SUM(CASE WHEN Bonus LIKE ''%[0-9]%'' THEN  CAST(Bonus AS DECIMAL) ELSE 0 END) total,
           COUNT(CASE WHEN Bonus = ''No Bonus'' THEN 1 END) cnt
    FROM T 
    GROUP BY Year,Name
)
SELECT Name, ' + @cols + ' 
from CTE
GROUP BY Name'

exec(@query) 

sqlfiddle

...