Count Distinct不起作用选择Oracle SQL

时间:2017-07-11 14:50:31

标签: sql oracle

我有一个SQL问题,其中代码无法统计不同的ID。它确实计算了它们,但并没有明确地这样做。我在下面提供了一小段代码并加粗了问题。

 SELECT
"RESERVATION_STAT_DAILY"."RESORT" AS "RESORT",
"RESERVATION_STAT_DAILY"."BUSINESS_DATE" AS "BUSINESS_DATE",
 to_char("RESERVATION_STAT_DAILY"."BUSINESS_DATE",'MON-yyyy') AS "MONTHYEAR",
 Extract(day from "RESERVATION_STAT_DAILY"."BUSINESS_DATE") AS "DAY",  
 Extract(month from "RESERVATION_STAT_DAILY"."BUSINESS_DATE") AS "MONTH",
 Extract(year from "RESERVATION_STAT_DAILY"."BUSINESS_DATE") AS "YEAR",
 "RESERVATION_STAT_DAILY"."SOURCE_CODE" AS "SOURCE_CODE",
 "RESERVATION_STAT_DAILY"."MARKET_CODE" AS "MARKET_CODE",
 "RESERVATION_STAT_DAILY"."RATE_CODE" AS "RATE_CODE",
 "RESERVATION_STAT_DAILY"."RESV_NAME_ID" AS "RESV_NAME_ID",
     (CASE WHEN "RESERVATION_STAT_DAILY"."SOURCE_CODE" = 'GDS' 
          AND "RESERVATION_STAT_DAILY"."RATE_CODE" NOT IN ('BKIT', 'EXPEDIA')
          AND "RESERVATION_STAT_DAILY"."MARKET_CODE" NOT IN ('GOVG', 'ENT')
     THEN 'GDS'
     ELSE 'Other'
END) AS "BizUnit",
COUNT(DISTINCT CASE WHEN "RESERVATION_STAT_DAILY"."SOURCE_CODE" = 'GDS' 
          AND "RESERVATION_STAT_DAILY"."RATE_CODE" NOT IN ('BKIT', 'EXPEDIA')
          AND "RESERVATION_STAT_DAILY"."MARKET_CODE" NOT IN ('GOVG', 'ENT')
     THEN "RESERVATION_STAT_DAILY"."RESV_NAME_ID" 
ELSE NULL   
END) AS "COST",

(SUM("RESERVATION_STAT_DAILY"."BUSINESS_DATE" - "RESERVATION_STAT_DAILY"."BUSINESS_DATE_CREATED")/(COUNT      ("RESERVATION_STAT_DAILY"."BUSINESS_DATE_CREATED"))) AS "DIFF",
SUM(NVL("RESERVATION_STAT_DAILY"."NIGHTS",0)) AS "NIGHTS",
SUM(NVL("RESERVATION_STAT_DAILY"."ROOM_REVENUE",0)) AS "ROOM_REVENUE"
FROM "OPERA"."RESERVATION_STAT_DAILY" "RESERVATION_STAT_DAILY"
Where RESORT in     ('558339','558341','4856','558340','602836','HCA','HZSD', 'TAC') and
BUSINESS_DATE < SYSDATE AND EXTRACT(year FROM "RESERVATION_STAT_DAILY"."BUSINESS_DATE_CREATED") >=2016
GROUP BY
"RESERVATION_STAT_DAILY"."RESORT",
"RESERVATION_STAT_DAILY"."BUSINESS_DATE",
  to_char("RESERVATION_STAT_DAILY"."BUSINESS_DATE",'MON-yyyy'),
  Extract(day from "RESERVATION_STAT_DAILY"."BUSINESS_DATE"),  
 Extract(month from "RESERVATION_STAT_DAILY"."BUSINESS_DATE"),
 Extract(year from "RESERVATION_STAT_DAILY"."BUSINESS_DATE"),
  "RESERVATION_STAT_DAILY"."SOURCE_CODE",
  "RESERVATION_STAT_DAILY"."MARKET_CODE",
  "RESERVATION_STAT_DAILY"."RATE_CODE", 
  "RESERVATION_STAT_DAILY"."RESV_NAME_ID",

  (  CASE 
WHEN (("RESERVATION_STAT_DAILY"."SOURCE_CODE" = 'GDS') AND ("RESERVATION_STAT_DAILY"."RATE_CODE" != 'BKIT' OR "RESERVATION_STAT_DAILY"."RATE_CODE" != 'EXPEDIA'
)) THEN 'GDS'
ELSE 'Other'
END )

2 个答案:

答案 0 :(得分:4)

清理代码的一些常规技巧,以及解决方案:

正如其他人所说,NOT IN条款在这里是完美的。将它们替换为!=比较的大块。您还希望COUNTSUM函数位于CASE语句之外,如下所示。

SELECT
    ...
    CASE WHEN "RESERVATION_STAT_DAILY"."SOURCE_CODE" = 'GDS' 
              AND "RESERVATION_STAT_DAILY"."RATE_CODE" NOT IN ('BKIT', 'EXPEDIA', ...)
              AND "RESERVATION_STAT_DAILY"."MARKET_CODE" NOT IN ('GOVG', 'ENT', ...)
         THEN 'GDS'
         ELSE 'Other'
    END AS "BizUnit",
    COUNT(DISTINCT CASE WHEN "RESERVATION_STAT_DAILY"."SOURCE_CODE" = 'GDS' 
              AND "RESERVATION_STAT_DAILY"."RATE_CODE" NOT IN ('BKIT', 'EXPEDIA', ...)
              AND "RESERVATION_STAT_DAILY"."MARKET_CODE" NOT IN ('GOVG', 'ENT', ...)
         THEN "RESERVATION_STAT_DAILY"."RESV_NAME_ID"
         ELSE NULL
    END) AS "COST",
    ...
FROM
    "OPERA"."RESERVATION_STAT_DAILY" "RESERVATION_STAT_DAILY"
WHERE
    ...
GROUP BY
    ...

您的代码超过570行。有些人认为1/10的代码太多了。请注意我是如何剪掉不直接适用于您的问题的部分的?这就是您创建minimal, complete, and verifiable working example.

的方法

答案 1 :(得分:3)

只是一些评论(评论时间太长):

  1. AND ("RESERVATION_STAT_DAILY"."RATE_CODE" != 'BKIT' OR "RESERVATION_STAT_DAILY"."RATE_CODE" != 'EXPEDIA' )?想一想。什么时候不满足这个条件?费率代码将始终不同于一个值或另一个(通常是两个),除了NULL,其结果是“未知”。
  2. THEN COUNT(DISTINCT "RESERVATION_STAT_DAILY"."RESV_NAME_ID") ELSE COUNT(DISTINCT "RESERVATION_STAT_DAILY"."RESV_NAME_ID") END) AS "COST"。所以在任何情况下你都算不同RESV_NAME_ID。为什么CASE呢?
  3. 当您按RESV_NAME_ID分组时,COUNT(DISTINCT "RESERVATION_STAT_DAILY"."RESV_NAME_ID")在一个组中始终只能为1。
  4. sum(NVL("RESERVATION_STAT_DAILY"."NIGHTS",0))sum(NVL("RESERVATION_STAT_DAILY"."ROOM_REVENUE",0))SUM忽略空值,因此您无需在添加之前创建这些零。总和可以为空,因此您可能需要NVL(SUM(NIGHTS), 0)
  5. 至于可读性:所有上限的查询都难以阅读。使用小写或混合两者(例如,SQL关键字的大写)。由于没有列包含空格等,因此您不需要引号。由于只涉及一个表,因此您不需要表限定符。如果你这样做了,你应该为表格提供一个简短的别名,并使用它来代替整个名称。您应该使用缩进格式化查询,因此我们会在第一眼看到子句(FROMGROUP BY等)。