繁体   English   中英

如何使用PIVOT简化或现代化此SQL语句?

[英]How can I use PIVOT to simplify or modernize this SQL statement?

下面我有一条创建5列的SQL语句(实际上是动态生成的)。 第一个是客户名称,第二个,第三个和第四个是每个月的记录数,第五个是最近一个月与上个月的差额。

SELECT ClientName AS 'Reporting',  
    (SELECT count(UMP.INDX) from UMP where ClientID=FRU.ClientID and LogActivityDate='20170101') 
  AS '20170101', 
    (SELECT count(UMP.INDX) from UMP where ClientID=FRU.ClientID and LogActivityDate='20170201') 
  AS '20170201', 
    (SELECT count(UMP.INDX) from UMP where ClientID=FRU.ClientID and LogActivityDate='20170301') 
  AS '20170301', 
       (SELECT count(UMP.INDX) from UMP where ClientID=FRU.ClientID and LogActivityDate='20170301')
      -(SELECT count(UMP.INDX) from UMP where ClientID=FRU.ClientID and LogActivityDate='20170201') 
  AS 'Difference' 

from FRU -- Removed: left outer join UMP on FRU.UnitID=UMP.UnitID 
  group by FRU.ClientName, FRU.ClientID 
  order by ClientName

这似乎是练习PIVOT技能的好时机,但是我没有任何机会。 您可以将其转换为使用PIVOT,以便我可以向您学习吗?

对于添加的惊奇值,这是我用来生成上述语句的实际SQL。 如果可以将其转换,我将欠您一项含糊不清的物品或服务。

我使用@coreSQL是因为我多次使用该部分,并对@qry进行了一些修改。

    DECLARE @qry nvarchar(max)

  --In modern SQL I use format(DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-2, 0),'yyyyMMdd')
  --In crappy old 2008 SQL:
  DECLARE @OneMonth varchar(8) = replace(convert(varchar, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0), 111), '/', '')
  DECLARE @TwoMonths varchar(8) = replace(convert(varchar, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-2, 0), 111), '/', '')
  DECLARE @ThreeMonths varchar(8) = replace(convert(varchar, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-3, 0), 111), '/', '')
  DECLARE @coreSQL varchar(max)

  SET @coreSQL = ' (SELECT count(UMP.INDX) from UMP where ClientID=FRU.ClientID and LogActivityDate=''' + @ThreeMonths + ''') AS ''' + @ThreeMonths + ''','
  SET @coreSQL = @coreSQL + ' (SELECT count(UMP.INDX) from UMP where ClientID=FRU.ClientID and LogActivityDate=''' + @TwoMonths + ''') AS ''' + @TwoMonths + ''','
  SET @coreSQL = @coreSQL + ' (SELECT count(UMP.INDX) from UMP where ClientID=FRU.ClientID and LogActivityDate=''' + @OneMonth + ''') AS ''' + @OneMonth + ''','
  SET @coreSQL = @coreSQL + ' (SELECT count(UMP.INDX) from UMP where ClientID=FRU.ClientID and LogActivityDate=''' + @OneMonth + ''')-(SELECT count(UMP.INDX) from UMP where ClientID=FRU.ClientID and LogActivityDate=''' + @TwoMonths + ''') AS ''Difference'''

  -- Raw results
  SET @qry = 'SELECT ClientName AS ''Reporting'', '
  SET @qry = @qry+@coreSQL
  SET @qry = @qry + ' from FRU group by FRU.ClientName, FRU.ClientID order by ClientName'

  EXECUTE sp_Executesql @qry

不需要PIVO:

SELECT
  ClientName AS 'Reporting',  
  SUM(CASE WHEN UMP.LogActivityDate='20170101' THEN 1 ELSE 0 END) AS '20170101', 
  SUM(CASE WHEN UMP.LogActivityDate='20170102' THEN 1 ELSE 0 END) AS '20170102', 
  SUM(CASE WHEN UMP.LogActivityDate='20170103' THEN 1 ELSE 0 END) AS '20170103', 
  SUM(CASE WHEN UMP.LogActivityDate='20170103' THEN 1 WHEN UMP.LogActivityDate='20170103' THEN -1 ELSE 0 END) AS 'Difference', 
  from FRU
  left outer join UMP on (FRU.UnitID=UMP.UnitID AND ClientID=FRU.ClientID)
  group by FRU.ClientName, FRU.ClientID 
  order by ClientName

希望对您有帮助...

SELECT
  ClientName,
  [20170101], [20170201], [20170301], [20170301] - [20170201] AS 'Difference'
FROM
  (
    SELECT FRU.ClientName, UMP.LogActivityDate, COUNT(1) AS Counted
    FROM FRU
    FULL JOIN UMP
      ON FRU.UnitID = UMP.UnitID AND
         FRU.ClientID = UMP.ClientID
    GROUP BY
      ClientName, LogActivityDate
  ) AS SourceTable
PIVOT
  (
    SUM(Counted)
    FOR LogActivityDate IN ([20170101], [20170201], [20170301])
  ) AS PivotTable

您的外部查询只会为您提供客户端名称。 与UMP的加入似乎完全是多余的。

顺便说一句,我看不出PIVOT如何在这里提供帮助。 我将使用条件聚合:

select 
  fru.clientname as "Reporting",
  coalesce(u.cnt20170101, 0) as "20170101",
  coalesce(u.cnt20170201, 0) as "20170201",
  coalesce(u.cnt20170301, 0) as "20170301",
  coalesce(u.cnt20170301, 0) - coalesce(u.cnt20170201, 0) as "difference"
from fru
left join
(
  select
    clientid, 
    count(case when logactivitydate = '20170101' then 1 end) as cnt20170101,
    count(case when logactivitydate = '20170201' then 1 end) as cnt20170201,
    count(case when logactivitydate = '20170301' then 1 end) as cnt20170301
  from ump
  group by clientid
) u on u.clientid = fru.clientid;

顺便说一句:单引号用于字符串文字,双引号用于别名。 (但是由于这是SQL Server,因此您可能必须将它们替换为非标准括号,例如as [Reporting]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM