简体   繁体   English

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

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

Below I have as SQL statement (that is actually generated dynamically) where I create 5 columns. 下面我有一条创建5列的SQL语句(实际上是动态生成的)。 The first is the client name, the second, third and fourth are the count of records for each month and the 5th is the difference between the most recent month and the previous month. 第一个是客户名称,第二个,第三个和第四个是每个月的记录数,第五个是最近一个月与上个月的差额。

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

This seems like a great time to practice my PIVOT skills but I don't have any. 这似乎是练习PIVOT技能的好时机,但是我没有任何机会。 Can you convert this to use PIVOT so I can learn from you? 您可以将其转换为使用PIVOT,以便我可以向您学习吗?

For added amaze-value, here's the actual SQL that I use to generate the above statement. 对于添加的惊奇值,这是我用来生成上述语句的实际SQL。 If you can convert this, I will owe you one ambiguously unidentifiable item or service. 如果可以将其转换,我将欠您一项含糊不清的物品或服务。

I use @coreSQL because I use that portion several more times with slight modifications to @qry. 我使用@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 is not needed : 不需要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

Hope it will helps you... 希望对您有帮助...

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

Your outer query only gets you the client name. 您的外部查询只会为您提供客户端名称。 The join with UMP seems completely superfluous. 与UMP的加入似乎完全是多余的。

I don't see how PIVOT can help here, by the way. 顺便说一句,我看不出PIVOT如何在这里提供帮助。 I'd use conditional aggregation: 我将使用条件聚合:

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;

BTW: Single quotes are for string literals, double quotes are for alias names. 顺便说一句:单引号用于字符串文字,双引号用于别名。 (But as this is SQL Server you may have to replace them by non-standard brackets, eg as [Reporting] . (但是由于这是SQL Server,因此您可能必须将它们替换为非标准括号,例如as [Reporting]

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

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