计数案例返回错误结果

时间:2018-08-05 07:58:21

标签: sql sql-server

我正在尝试计算在不到30分钟且超过30分钟内关闭的订单数。

表结构和示例数据

ORDERID  CUSTOMERID  ORDERDATE              CLOSEDDATE               STATUSID
---------------------------------------------------------------------------------
14        1         2018-07-03 11:02:54.000 2018-07-03 13:15:58.000  CLOSED
15        1         2018-07-03 13:22:42.000 NULL                     DISPATCHED
16        1         2018-07-03 13:26:04.000 NULL                     DISPATCHED
17        1         2018-07-03 13:27:57.000 2018-07-03 13:28:28.000  CLOSED
18        1         2018-07-03 17:23:45.000 NULL                     RECEIVED

查询:

SELECT
    OUTLETNAME,
    COUNT(ORDERID) AS ORDERSCOUNT,
    COUNT(DISTINCT(dbo.VW_SALES_SUM.CUSTOMERID)) AS CUSTOMERCOUNT,
    COUNT(CASE WHEN DATEDIFF(mi, dbo.VW_SALES_SUM.ORDERDATE, dbo.VW_SALES_SUM.CLOSEDDATE) < 30 AND dbo.VW_SALES_SUM.STATUSID = 'CLOSED'   
                  THEN 1 
                  ELSE 0
          END) [LESS 30 (CLOSED)],
    COUNT(CASE WHEN DATEDIFF(mi, dbo.VW_SALES_SUM.ORDERDATE, dbo.VW_SALES_SUM.CLOSEDDATE) > 30 AND dbo.VW_SALES_SUM.STATUSID = 'CLOSED'   
                  THEN 1 ELSE 0 
          END) [Greater 30 (CLOSED)]
FROM 
    dbo.VW_SALES_SUM
INNER JOIN 
    dbo.[OUTLET] ON dbo.VW_SALES_SUM.OUTLETCODE = dbo.[OUTLET].CODE
WHERE 
    dbo.VW_SALES_SUM.ORDERDATE BETWEEN '7/3/2018 11:00:00 AM' AND '7/4/2018 02:00:00 AM'
GROUP BY 
    OUTLETNAME, dbo.OUTLET.BRAND
ORDER BY 
    COUNT(ORDERID) DESC

输出:

OUTLETNAME  ORDERSCOUNT CUSTOMERCOUNT   LESS 30 (CLOSED)    IN 30 (CLOSED)
--------------------------------------------------------------------------
shop1        5           1              5                   5

从输出中我们可以看到它返回的已关闭订单计数错误,它总是返回订单总数。

输出应如下所示:

OUTLETNAME  ORDERSCOUNT CUSTOMERCOUNT   LESS 30 (CLOSED)    Greater 30 (CLOSED)
-------------------------------------------------------------------------
shop1        5           1              0                   2

2 个答案:

答案 0 :(得分:1)

而不是同时计算1和0。您要做的就是不同时计算两者。

问题是,按值计数不计入NULL。
但是,当CASE WHEN仅返回值0或1时,COUNT的行为与COUNT(*)相同。由于它不会为COUNT忽略而返回任何NULL。

所以只需删除那些SELECT OUTLETNAME, COUNT(ORDERID) AS ORDERSCOUNT, COUNT(DISTINCT(s.CUSTOMERID)) AS CUSTOMERCOUNT, COUNT(CASE WHEN DATEDIFF(mi, s.ORDERDATE, s.CLOSEDDATE) < 30 AND s.STATUSID = 'CLOSED' THEN 1 END) [LESS 30 (CLOSED)], COUNT(CASE WHEN DATEDIFF(mi, s.ORDERDATE, s.CLOSEDDATE) > 30 AND s.STATUSID = 'CLOSED' THEN 1 END) [Greater 30 (CLOSED)] FROM dbo.VW_SALES_SUM s JOIN dbo.[OUTLET] o ON o.CODE = s.OUTLETCODE WHERE s.ORDERDATE BETWEEN '7/3/2018 11:00:00 AM' AND '7/4/2018 02:00:00 AM' GROUP BY OUTLETNAME, o.BRAND ORDER BY COUNT(ORDERID) DESC ,就可以了。

顺便说一句,使用别名可以缩短您的SQL。

SELECT COUNT(DISTINCT CASE WHEN col1='bar' then col2 END) AS Bars FROM Foo;

您也可以将COUNT替换为SUM。但是COUNT的优点是您可以将其与DISTINCT结合使用,以便仅计算不为NULL的唯一值。

例如:

return redirect('home')->with('success', 'Group is created!');

答案 1 :(得分:0)

使用SUM代替计数

SELECT
    OUTLETNAME,
    COUNT(ORDERID) AS ORDERSCOUNT,
    COUNT(distinct(dbo.VW_SALES_SUM.CUSTOMERID)) as CUSTOMERCOUNT,
    SUM(case when DATEDIFF(mi, dbo.VW_SALES_SUM.ORDERDATE, dbo.VW_SALES_SUM.CLOSEDDATE) < 30 and dbo.VW_SALES_SUM.STATUSID='CLOSED'   then 1 else 0 end) [LESS 30 (CLOSED)],
    SUM(case when DATEDIFF(mi, dbo.VW_SALES_SUM.ORDERDATE,  dbo.VW_SALES_SUM.CLOSEDDATE) > 30 and dbo.VW_SALES_SUM.STATUSID='CLOSED'   then 1 else 0 end) [Greater 30 (CLOSED)]
FROM 
    dbo.VW_SALES_SUM
INNER JOIN 
    dbo.[OUTLET] ON dbo.VW_SALES_SUM.OUTLETCODE = dbo.[OUTLET].CODE
WHERE 
    dbo.VW_SALES_SUM.ORDERDATE BETWEEN '7/3/2018 11:00:00 AM' AND '7/4/2018 02:00:00 AM'
GROUP BY 
    OUTLETNAME, dbo.OUTLET.BRAND
ORDER BY 
    COUNT(ORDERID) DESC