簡體   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