从日期字段中获得不同的计数

时间:2019-07-01 09:48:18

标签: sql tsql

我有一段代码正在寻找不同数量的小桶,已标记的不同小桶的数量和未标记的小桶的数量,到目前为止,我的了解是:

with CTE as
(select UID_KEG, IS_TAGGED, movement_date
from MOVEMENT M
inner join Keg on M.UID_Keg = Keg.Unique_ID
where DATEPART(year,Movement_date) = '2019'
and UID_MOVEMENT_TYPE = 1
)
select COUNT(Distinct CTE.UID_KEG) as 'Kegs', datepart(week,movement_date) 
as 'Week number',
SUM(case when Is_Tagged = 1 then 1 end) as 'tagged',
SUM(case when Is_Tagged = 0 then 1 end) as 'untagged' 
from CTE
group by datepart(week,movement_date)
order by [Week number] asc

它会立即返回不同数量的小桶,但是带标签的和未带标签的数字是错误的,我只能假设是因为它正在计数重复的小桶。 有人可以建议我如何解决这个问题,还是只依靠不同的小桶?

2 个答案:

答案 0 :(得分:0)

如果您从计数中除去Distinct,则未开发和已开发的总和应等于总数(如果它是二进制0或1)。这表明您有重复的UID_KEG值。花一些时间来了解原因。问题的部分原因是您似乎不太了解数据集的形状。

花一些时间查看数据以了解是否存在重复项(为什么?是由联接引起的,还是它们在基础数据中?),请查看它们是否可以显示为已标记和未标记。< / p>

编辑:针对您的评论。如果可以对它们进行两次扫描,则必须假设如果当天的任何UID_KEG的Is_Tagged = 1,那么所有带有该UID_KEG的小桶都会被标记。

在这种情况下,您将不得不修改代码以使用此假设。

WITH CTE
AS (
    SELECT UID_KEG
        ,IS_TAGGED
    ,movement_date
    FROM MOVEMENT M
    INNER JOIN Keg ON M.UID_Keg = Keg.Unique_ID
    WHERE DATEPART(year, Movement_date) = '2019'
    AND UID_MOVEMENT_TYPE = 1
)
SELECT CTE.UID_KEG AS 'Kegs'
    ,datepart(week, movement_date) AS 'Week number'
    ,MAX(Is_Tagged) AS 'tagged'
FROM CTE
GROUP BY CTE.UID_KEG
    ,datepart(week, movement_date)
ORDER BY [Week number] ASC

此代码可能并不完美,我无法对其进行测试,但是它应该为您提供每一天每一桶的完整列表,以及该桶是否至少被标记为已标记一次,如果没有,标记为已标记。

这里最重要的是每天消除小桶的重复,然后才可以计算。

我对CTE不太满意,但是您需要将一个级别汇总到每日级别,现在您将能够计算不同数量的小桶以及标记和未标记的小桶。

希望如此。

编辑:这是应该正常工作的子查询

SELECT [Week number]
    ,count(1) [numKegs]
    ,sum(tagged) [numTagged]
FROM (
    SELECT UID_KEG AS 'Kegs'
        ,datepart(week, movement_date) AS 'Week number'
        ,MAX(IS_TAGGED) AS 'tagged'
    FROM MOVEMENT M
    INNER JOIN Keg ON M.UID_Keg = Keg.Unique_ID
    WHERE DATEPART(year, Movement_date) = '2019'
        AND UID_MOVEMENT_TYPE = 1
    GROUP BY UID_KEG
        ,datepart(week, movement_date)
    ) kegdailylevel
GROUP BY [Week number]
ORDER BY [Week number] ASC

答案 1 :(得分:0)

您想要使用COUNT(DISTINCT)进行条件聚合。那应该是:

SELECT COUNT(DISTINCT CTE.UID_KEG) as Kegs, 
       datepart(week, movement_date) as Week_number,
       COUNT(DISTINCT CASE WHEN Is_Tagged = 1 THEN CTE.UID_KEG END) as tagged,
       COUNT(DISTINCT(CASE WHEN Is_Tagged = 0 THEN CTE.UID_KEG END) as untagged 
FROM CTE
GROUP BY datepart(week, movement_date)
ORDER BY MIN(movement_date);

注意:

  • 假设小桶可以在一周内同时进行标记和未标记,那么标记和未标记的总数仍可能超过总数。
  • 您应该同时包括year()和星期,尤其是因为您不是从一年中选择数据。
  • 仅对字符串和日期常量使用单引号。不要将它们用作列别名。可能导致难以调试的错误。