【问题标题】:Use COUNT() for multiple columns over several years在几年内对多个列使用 COUNT()
【发布时间】:2021-12-18 06:30:05
【问题描述】:

我有一个查询,显示当年的井数。我想显示过去 5 年的计数/年。我怎么能在一个查询中做到这一点?

今年,我使用的是YEAR(GETDATE())。在过去的五年里,我一直在想我可以使用:YEAR(GETDATE())-1YEAR(GETDATE())-2YEAR(GETDATE())-23 等。我还认为CASE WHEN 子句可以工作,但不确定如何在@987654330 下使用它@ 声明。

这是我当前的查询:

SELECT
    COALESCE(w.WellType, 'Totals') AS 'WellTypes',
    COUNT(DISTINCT(w.WellID)) AS '2021'
FROM Well w
    LEFT JOIN Construct c ON c.WellKey = w.PKey
    LEFT JOIN ConstructDate cd ON c.PKey = cd.ConstructKey
WHERE
    YEAR(cd.EventDate) = YEAR(GETDATE())
    AND cd.Event = 'LATERALSTATUS'
    AND cd.Comment = 'PA'
GROUP BY ROLLUP(w.WellType)
ORDER BY
    CASE w.WellType
        WHEN 'OW' THEN 1
        WHEN 'GW' THEN 2
        WHEN 'D' THEN 3
        WHEN 'OWI' THEN 4
        WHEN 'WI' THEN 5
    END DESC

这是我目前的结果:

WellTypes 2021
WI 10
OWI 1
D 21
GW 40
OW 72
Totals 144

这是我想要的:

WellTypes 2021 2020 2019 2018 2017
WI 10 6 0 5 2
OWI 1 2 3 6 5
D 21 0 0 2 0
GW 40 6 2 0 7
OW 72 1 2 3 4
Totals 144 15 7 14 18

我正在努力在 db-fiddle 中使用它,但我以前从未使用过它。我知道这很长,但现在,这是表格中的纯数据。 “EventDate”、“Comment”和“Event”列来自名为“ConstructDate”的表。 “WellType”列来自名为“Well”的表。

EventDate WellType Comment Event
1/2/2017 OW PA LATERALSTATUS
1/3/2017 OW PA LATERALSTATUS
1/3/2017 OW PA LATERALSTATUS
1/3/2017 OW PA LATERALSTATUS
1/3/2017 WI PA LATERALSTATUS
1/3/2017 WI PA LATERALSTATUS
1/3/2017 OWI PA LATERALSTATUS
1/3/2017 OWI PA LATERALSTATUS
1/3/2017 OWI PA LATERALSTATUS
1/3/2017 OWI PA LATERALSTATUS
1/3/2017 OWI PA LATERALSTATUS
1/4/2017 GW PA LATERALSTATUS
1/4/2017 GW PA LATERALSTATUS
1/5/2017 GW PA LATERALSTATUS
1/5/2017 GW PA LATERALSTATUS
1/5/2017 GW PA LATERALSTATUS
1/5/2017 GW PA LATERALSTATUS
1/5/2017 GW PA LATERALSTATUS
1/1/2018 WI PA LATERALSTATUS
1/2/2018 WI PA LATERALSTATUS
1/2/2018 WI PA LATERALSTATUS
1/2/2018 WI PA LATERALSTATUS
1/2/2018 WI PA LATERALSTATUS
1/2/2018 OWI PA LATERALSTATUS
1/2/2018 OWI PA LATERALSTATUS
1/2/2018 OWI PA LATERALSTATUS
1/2/2018 OWI PA LATERALSTATUS
1/2/2018 OWI PA LATERALSTATUS
1/2/2018 OWI PA LATERALSTATUS
1/2/2018 D PA LATERALSTATUS
1/2/2018 D PA LATERALSTATUS
1/2/2018 OW PA LATERALSTATUS
1/2/2018 OW PA LATERALSTATUS
1/2/2018 OW PA LATERALSTATUS
1/2/2019 OWI PA LATERALSTATUS
1/2/2019 OWI PA LATERALSTATUS
1/2/2019 OWI PA LATERALSTATUS
1/2/2019 GW PA LATERALSTATUS
1/2/2019 GW PA LATERALSTATUS
1/2/2019 OW PA LATERALSTATUS
1/2/2019 OW PA LATERALSTATUS
1/1/2020 WI PA LATERALSTATUS
1/2/2020 WI PA LATERALSTATUS
1/2/2020 WI PA LATERALSTATUS
1/2/2020 WI PA LATERALSTATUS
1/2/2020 WI PA LATERALSTATUS
1/2/2020 WI PA LATERALSTATUS
1/2/2020 OWI PA LATERALSTATUS
1/2/2020 OWI PA LATERALSTATUS
1/2/2020 GW PA LATERALSTATUS
1/2/2020 GW PA LATERALSTATUS
1/2/2020 GW PA LATERALSTATUS
1/2/2020 GW PA LATERALSTATUS
1/2/2020 GW PA LATERALSTATUS
1/2/2020 GW PA LATERALSTATUS
1/2/2020 OW PA LATERALSTATUS
8/16/2021 WI PA LATERALSTATUS
8/16/2021 WI PA LATERALSTATUS
8/16/2021 WI PA LATERALSTATUS
8/16/2021 WI PA LATERALSTATUS
8/16/2021 WI PA LATERALSTATUS
8/16/2021 WI PA LATERALSTATUS
8/16/2021 WI PA LATERALSTATUS
8/16/2021 WI PA LATERALSTATUS
8/16/2021 WI PA LATERALSTATUS
8/16/2021 WI PA LATERALSTATUS
8/16/2021 OWI PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 D PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/16/2021 GW PA LATERALSTATUS
8/17/2021 GW PA LATERALSTATUS
8/17/2021 GW PA LATERALSTATUS
8/17/2021 GW PA LATERALSTATUS
8/17/2021 GW PA LATERALSTATUS
8/17/2021 GW PA LATERALSTATUS
8/17/2021 GW PA LATERALSTATUS
8/17/2021 GW PA LATERALSTATUS
8/17/2021 GW PA LATERALSTATUS
8/17/2021 GW PA LATERALSTATUS
8/18/2021 GW PA LATERALSTATUS
8/17/2021 GW PA LATERALSTATUS
8/17/2021 GW PA LATERALSTATUS
8/17/2021 OW PA LATERALSTATUS
8/17/2021 OW PA LATERALSTATUS
8/18/2021 OW PA LATERALSTATUS
8/18/2021 OW PA LATERALSTATUS
8/18/2021 OW PA LATERALSTATUS
8/19/2021 OW PA LATERALSTATUS
8/19/2021 OW PA LATERALSTATUS
8/19/2021 OW PA LATERALSTATUS
8/19/2021 OW PA LATERALSTATUS
8/19/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/20/2021 OW PA LATERALSTATUS
8/21/2021 OW PA LATERALSTATUS
8/21/2021 OW PA LATERALSTATUS
8/21/2021 OW PA LATERALSTATUS
8/21/2021 OW PA LATERALSTATUS
8/21/2021 OW PA LATERALSTATUS
8/21/2021 OW PA LATERALSTATUS
8/21/2021 OW PA LATERALSTATUS
8/22/2021 OW PA LATERALSTATUS
8/22/2021 OW PA LATERALSTATUS
8/23/2021 OW PA LATERALSTATUS
8/23/2021 OW PA LATERALSTATUS
8/23/2021 OW PA LATERALSTATUS
8/23/2021 OW PA LATERALSTATUS
8/23/2021 OW PA LATERALSTATUS
8/23/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS
8/24/2021 OW PA LATERALSTATUS

【问题讨论】:

  • 您能否将示例数据包含在您的预期结果中 - 最好是 DB<>Fiddle 或作为您问题中的文本。
  • @Stu 预期的数据已经组成。让我看看我能不能把东西放在一起。它基本上是两列数据:一列显示日期,另一列显示井类型。
  • 旁白:WHERE YEAR(cd.EventDate) = YEAR(GETDATE())效率低,因为列上的函数(不能使用索引),最好使用WHERE cd.EventDate &gt;= DATEFROMPARTS(YEAR(GETDATE()) -4, 1, 1)。由于WHERE 子句,您的左连接变为内连接。而不是COALESCE(w.WellType, 'Totals'),最好使用CASE WHEN GROUPING(w.WellType) = 0 THEN w.WellType ELSE 'Totals' END。您不应该使用'' 单引号来分隔列名,而是使用[]
  • @Charlieface 为什么使用CASE WHEN GROUPING(w.WellType) = 0 THEN w.WellType ELSE 'Totals' END 而不是COALESCE(w.WellType, 'Totals')
  • 主要是因为如果WellType也可以为null,那么会有两个空行,一个用于nul,一个用于总数。它也使意图更清晰

标签: sql sql-server tsql count sql-server-2012


【解决方案1】:

当您需要不同的约束来聚合您想要的内容时,这很棘手。我不会使用计数,而是使用 CASE 语句对实例求和。这是您可以在 SQL Server 上的会话中运行的示例:

IF OBJECT_ID('TEMPDB..#TEMP') IS NOT NULL
    DROP TABLE #TEMP

CREATE TABLE #TEMP(
    WellType            NVARCHAR(10)
    ,EventDate          DATE
)
INSERT INTO #TEMP (WellType, EventDate)
VALUES ('OW','2021-11-03')
    ,('GW','2020-11-03')
    ,('D','2019-11-03')
    ,('OWI','2018-11-03')
    ,('WI','2017-11-03')
    ,('WI','2021-11-03')
    ,('D','2020-11-03')
    ,('D','2019-11-03')
    ,('GW','2018-11-03')
    ,('OW','2017-11-03')
    ,('OW','2021-11-03')
    ,('GW','2020-11-03')
    ,('D','2019-11-03')
    ,('OWI','2018-11-03')
    ,('WI','2017-11-03')
    ,('WI','2021-11-03')
    ,('D','2020-11-03')
    ,('D','2019-11-03')
    ,('GW','2018-11-03')
    ,('OW','2017-11-03')

SELECT 
    WellType
    ,SUM(CASE WHEN YEAR(EventDate) = YEAR(GETDATE()) THEN 1 ELSE 0 END) [THIS YEAR]
    ,SUM(CASE WHEN YEAR(EventDate) = YEAR(DATEADD(YEAR,-1,GETDATE())) THEN 1 ELSE 0 END) [LAST YEAR]
    ,SUM(CASE WHEN YEAR(EventDate) = YEAR(DATEADD(YEAR,-2,GETDATE())) THEN 1 ELSE 0 END) [2 YEARS AGO]
    ,SUM(CASE WHEN YEAR(EventDate) = YEAR(DATEADD(YEAR,-3,GETDATE())) THEN 1 ELSE 0 END) [3 YEARS AGO]
FROM #TEMP
GROUP BY WellType

我还使用 GETDATE() 函数来确定对哪一年求和。这应该可以满足您的需求。

SELECT 语句之前和之后的输出:

【讨论】:

  • 这行得通,除了我必须用COALESCE(w.WellType, 'Totals') AS 'WellTypes' 替换SELECT 下的Welltype 才能让我的Totals 行工作。
【解决方案2】:

如果没有涉及的表和相关数据,我无法重现您自己的查询,但是有多种方法可以将您需要的数据转换为列。

一种方法是使用conditional case expression,另一种方法是使用window analytic functions

select distinct welltype, 
    Count(case when Year(Eventdate)=Year(GetDate())-0 then 1 end) over(partition by welltype ) [2021],
    Count(case when Year(Eventdate)=Year(GetDate())-1 then 1 end) over(partition by welltype ) [2020],
    Count(case when Year(Eventdate)=Year(GetDate())-2 then 1 end) over(partition by welltype ) [2019],
    Count(case when Year(Eventdate)=Year(GetDate())-3 then 1 end) over(partition by welltype ) [2018],
    Count(case when Year(Eventdate)=Year(GetDate())-4 then 1 end) over(partition by welltype ) [2017]
from t 

Demo Fiddle

【讨论】:

  • 我很难在合理的时间内将 db-fiddle 放在一起。现在,我添加了一个包含所有示例数据的表。这些帮助有用?如果您需要我澄清有关数据的任何内容,请告诉我。
  • @Hiebs915 我添加了一个演示DB<>Fiddle 链接。
  • 我刚刚添加了两列用于WHERE 子句的数据。我不认为他们会有所作为。但我需要最终使用它们。
  • 您发布的部分有效,但是当我与现有的 GROUP BYORDER BY 子句合并时,我收到两个错误:“列 'ConstructDate.EventDate' 在选择列表中无效,因为它是不包含在聚合函数或 GROUP BY 子句中”和“如果指定了 SELECT DISTINCT,则 ORDER BY 项必须出现在选择列表中”。 ORDER BY 错误是我的错,井类型比我在原始查询中列出的要多。删除我的 ORDER BY 子句并将 cd.EventDate 添加到 GROUP BY 子句后,您的答案有效。
  • 如果要修改示例数据,按理说你需要修改它。
【解决方案3】:

很遗憾,我无法在没有数据的情况下验证请求。我会尝试使用“Grouping Set”运算符结合“Case When”结构进行子查询,然后使用“SUM”聚合函数。

With Cte As (Select YEAR(GetDate()) As [YEAR], YEAR(GetDate())-4 As [first]             
             Union All 
             Select [YEAR]-1 As [YEAR], [first]
             From cte
             Where [YEAR] > [first])
Select WellTypes, SUM([2021]), SUM([2020]), SUM([2019]), SUM([2018]), SUM([2017])
From
(Select
    COALESCE(w.WellType, 'Totals') As WellTypes,
    Case When cte.[YEAR] = YEAR(GetDate()) Then COUNT(DISTINCT(w.WellID)) End As [2021],
    Case When cte.[YEAR] = Year(GetDate())-1 Then COUNT(DISTINCT(w.WellID)) End As [2020],
    Case When cte.[YEAR] = Year(GetDate())-2 Then COUNT(DISTINCT(w.WellID)) End As [2019],
    Case When cte.[YEAR] = Year(GetDate())-3 Then COUNT(DISTINCT(w.WellID)) End As [2018],
    Case When cte.[YEAR] = Year(GetDate())-4 Then COUNT(DISTINCT(w.WellID)) End As [2017]
From Well w
    Inner Join Construct c ON c.WellKey = w.PKey
    Inner Join ConstructDate cd ON c.PKey = cd.ConstructKey
    Inner Join cte On (YEAR(cd.EventDate)=cte.[YEAR])
Where
    And cd.Event = 'LATERALSTATUS'
    And cd.Comment = 'PA'
Group by Grouping Sets ((cte.[YEAR], w.WellType), (cte.[YEAR]))) As T
Group by WellTypes
Order by
    Case WellTypes
        When 'OW' Then 1
        When 'GW' Then 2
        When 'D' Then 3
        When 'OWI' Then 4
        When 'WI' Then 5
    End Desc

【讨论】:

  • 除了Where 下的第一个And 需要删除之外,此方法有效。
猜你喜欢
  • 1970-01-01
  • 2015-01-05
  • 2021-08-31
  • 2017-09-21
  • 2012-05-25
  • 1970-01-01
  • 2016-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多