oracle sql count case语句返回所有列的总和

时间:2018-03-20 15:59:47

标签: sql oracle11g

我有一个查询,我试图通过每周的每一天的pers id来计算每天的交易次数,我看到的是我无法弄清楚的事情。我没有显示每天的计数,而是获得每天所有日期的计数总和'柱。这是我的剧本:

    Select distinct
    pers.prsid, 

    count(case when trim(to_char(transaction.actdatetime, 'day')) = 'Monday' THEN transaction.rtxnnbr ELSE 0 END) as "Monday",

    count(case when trim(to_char(transaction.actdatetime, 'day')) = 'Tuesday' THEN transaction.rtxnnbr ELSE 0 END) as "Tuesday",

    count(case when trim(to_char(transaction.actdatetime, 'day')) = 'Wednesday' THEN transaction.rtxnnbr ELSE 0 END) as "Wednesday",

    count(case when trim(to_char(transaction.actdatetime, 'day')) = 'Thursday' THEN transaction.rtxnnbr ELSE 0 END) as "Thursday",

    count(case when trim(to_char(transaction.actdatetime, 'day')) = 'Friday' THEN transaction.rtxnnbr ELSE 0 END) as "Friday"

    FROM PERS, TRANSACTION 

    WHERE 
    ((TRANSACTION.POSTDATE between TO_DATE('03-05-2018','MM-DD-YYYY') AND TO_DATE('03-09-2018','MM-DD-YYYY')) 
AND ((TRANSACTION.ORIGPERSNBR = PERS.PERSID(+)))

输出:

prsid   Monday  Tuesday Wednesday   Thursday    Friday
1050    60      60      60          60          60
1090    66      66      66          66          66

我期待看到的内容:

prsid   Monday  Tuesday Wednesday   Thursday    Friday
1050    10      15      5           19          11
1090    15      11      20          6           14

编辑:添加了我忘记复制的表格连接

3 个答案:

答案 0 :(得分:0)

我建议以下查询:

SELECT
    p.prsid, 
    SUM(CASE WHEN TRIM(TO_CHAR(r.actdatetime, 'day')) = 'Monday' THEN t.rtxnnbr ELSE 0 END) AS "Monday",
    SUM(CASE WHEN TRIM(TO_CHAR(t.actdatetime, 'day')) = 'Tuesday' THEN t.rtxnnbr ELSE 0 END) AS "Tuesday",
    SUM(CASE WHEN TRIM(TO_CHAR(t.actdatetime, 'day')) = 'Wednesday' THEN t.rtxnnbr ELSE 0 END) AS "Wednesday",
    SUM(CASE WHEN TRIM(TO_CHAR(t.actdatetime, 'day')) = 'Thursday' THEN t.rtxnnbr ELSE 0 END) AS "Thursday",
    SUM(CASE WHEN TRIM(TO_CHAR(t.actdatetime, 'day')) = 'Friday' THEN t.rtxnnbr ELSE 0 END) as "Friday"
FROM PERS p
INNER JOIN TRANSACTION t
    ON p.TRANS_ID = t.ID
WHERE 
    t.POSTDATE BETWEEN TO_DATE('03-05-2018','MM-DD-YYYY') AND
    TO_DATE('03-09-2018','MM-DD-YYYY'
GROUP BY
    p.prsid

关键点是您可能打算加入人员和交易表。此外,根据您的案例表达式,您可能打算将rtxnnbr字段求和,而不是计算它。您不需要使用不同的,而是使用GROUP BY按人聚合。

答案 1 :(得分:0)

嗯,你需要一个join条件:

FROM PERS JOIN
     TRANSACTION 
     ON PERS.? = TRANSACTION.?

如果您始终使用显式JOIN语法,则不会出现此问题。

至于编写查询,我会选择:

SELECT pers.prsid, 
       sum(case when to_char(t.actdatetime, 'DY') = 'MON' THEN 1 ELSE 0 END) as "Monday",
       sum(case when to_char(t.actdatetime, 'DY') = 'TUE' THEN 1 ELSE 0 END) as "Tuesday",
       sum(case when to_char(t.actdatetime, 'DY') = 'WED' THEN 1 ELSE 0 END) as "Wednesday",
       sum(case when to_char(t.actdatetime, 'DY') = 'THU' THEN 1 ELSE 0 END) as "Thursday",
       sum(case when to_char(t.actdatetime, 'DY') = 'FRI' THEN 1 ELSE 0 END) as "Friday"
FROM PERS p JOIN
     TRANSACTION t
     ON p.? = t.?  -- probably prsid
WHERE t.POSTDATE >= DATE '2018-03-05' AND
      t.POSTDATE < DATE '2018-03-10'
GROUP BY p.prsid;

注意:

  • 使用DATE常量,以及日期常量。此外,>=<有助于避免出现问题 - 尤其是在DATE数据类型具有时间组件并且通常仅使用日期打印出来的数据库中。
  • 使用明确的GROUP BY。您有一个聚合查询。要自豪并使用GROUP BY
  • TRIM()使用完整的工作日名称是正确的。但是,使用三个字符缩写更简单。

答案 2 :(得分:0)

当您count计算所有not null值时,ELSE 0始终会返回一个值。

删除它:

count(case when trim(to_char(transaction.actdatetime, 'day')) = 'Monday' 
           THEN transaction.rtxnnbr END) as "Monday",

或切换到SUM(0/1)

SUM(case when trim(to_char(transaction.actdatetime, 'day')) = 'Monday' 
         THEN 1 ELSE 0 END) as "Monday",