【问题标题】:How to select values for count in oracle sql如何在 oracle sql 中选择计数值
【发布时间】:2016-09-26 09:36:53
【问题描述】:

感谢我的一个朋友,我已经能够获得以下代码,它可以根据 30 分钟的差异计算日期/时间。如果差异小于 30 分钟,则计数保持不变,否则如果大于计数,则增加 1。

SELECT
CASE  
      WHEN DATE2 - LAG(DATE2) over (PARTITION BY NAME, TRUNC(DATE2) ORDER BY DATE2) <= 1 / 48  
        THEN NULL
        ELSE 1
      END AS COUNT1
FROM TABLE1

我忘记要求他包括的是已计为该计数的开始时间和结束时间的值,因为这可以让我计算花费了多长时间,但我不确定如何添加这个基于上面的代码,所以没有尝试任何东西。

如果有人能建议我如何带来这样的东西,我将不胜感激,因为 sql 不是我的强项。

以下是一些示例数据:

NAME | DATE2
Humpty Dumpty | 21-JUL-16 09:27:24
Humpty Dumpty | 21-JUL-16 09:27:24
Humpty Dumpty | 21-JUL-16 09:27:24
Humpty Dumpty | 21-JUL-16 09:27:24
Humpty Dumpty | 21-JUL-16 09:31:31
Humpty Dumpty | 21-JUL-16 09:31:31
Humpty Dumpty | 21-JUL-16 09:31:31
Humpty Dumpty | 21-JUL-16 09:31:31
Humpty Dumpty | 21-JUL-16 16:42:03
Humpty Dumpty | 21-JUL-16 16:42:03
Humpty Dumpty | 21-JUL-16 16:42:03
Humpty Dumpty | 21-JUL-16 16:42:03

当我运行上述查询时,我得到以下信息:

Count1
1
(null)
(null)
(null)
(null)
(null)
(null)
(null)
1
(null)
(null)
(null)

这给了我一个值,但我还需要知道第一个值是什么时候计算的 1,以及计算下一个值之前的最后一个值。

从上面我的结果应该是这样的:

Count1 | Start_time | End_Time
1 | 21-JUL-16 09:27:24 | 21-JUL-16 09:31:31
1 | 21-JUL-16 16:42:03 | 21-JUL-16 16:42:03

需要指出的是,如果半小时内同一日期还有另一个值,那么开始时间也是结束时间..

【问题讨论】:

  • 你也可以显示一些示例数据吗?这将使您的问题(以及任何答案)对可能面临类似问题的其他人更有用。
  • @TimBiegeleisen - 您可以在 OTN 上找到示例数据,几天前提出了原始问题。 community.oracle.com/thread/3974725
  • @mathguy 感谢您的侦探工作,但问题至少应该在这里直接包含一些示例数据。
  • @TimBiegeleisen - 没有侦探工作,真的;我相信 OP 显示的实际上是我在该线程中给出的答案 :-) 我同意,但 OP 应该在此处提供示例数据。
  • “你的朋友”给你的答案与你上一个问题的the answer I posted 相当接近。你不应该以这种方式浪费人们的善意。表现不佳

标签: sql oracle count case


【解决方案1】:

您想要识别不同的组。因为您使用的是lag() 方法,所以我将继续这样做。下一步是累积和,然后是聚合:

SELECT NAME, TRUNC(DATE2), MIN(DATE2), MAX(DATE2)
FROM (SELECT t1.*,
             SUM(COUNT1) OVER (PARTITION BY NAME, TRUNC(DATE2) ORDER BY DATE2) as grp
      FROM (SELECT t1.*,
                   (CASE WHEN DATE2 - LAG(DATE2) over (PARTITION BY NAME, TRUNC(DATE2) ORDER BY DATE2) <= 1/48  
                         THEN 0 ELSE 1
                    END) AS COUNT1
            FROM TABLE1 t1
           ) t1
      ) t1
GROUP BY NAME, TRUNC(DATE2), grp;

【讨论】:

  • 感谢 Gordon 成功了!只是出于好奇,我怎样才能仍然从滞后查询中添加触摸计数来给我一个总数,或者我可以根据名称、日期进行计数,这仍然会给我相同的数字
  • @user3191160 。 . .我不知道什么是“触摸计数”。新问题应该作为 cmets 中没有的问题提出。
  • 对不起,这不是一个新问题,它最初的案例陈述给了我计数......
  • 假设原始数据中的每一行都是一个触摸,那么您需要做的就是将 COUNT(*) 添加到 Gordon 答案中的选择列表中。这将告诉您开始和结束时间之间的总行数
【解决方案2】:
DATE2

是当前行的时间 - 在计算中这是结束时间

LAG(DATE2) over (PARTITION BY NAME, TRUNC(DATE2) ORDER BY DATE2)

是前一行的时间(按日期排序) - 在计算中这是开始时间

真的就这么简单。

我已更新以下内容以(希望)符合您更新后的要求。

查询 A 使用 LAG 和 LEAD 函数来确定每一行是位于一组条目的开头(前一行相差 > 30 分钟)还是一组条目的末尾(下一行相差 > 30 分钟)

然后查询 B 限制结果行是开始行或结束行(其他一切都只是噪音)

最后每个开始和结束都连接在一起成为一行。

WITH
 test_data (name, date2) AS
  (SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 09:27:24','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 09:27:24','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 09:27:24','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 09:27:24','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 09:31:31','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 09:31:31','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 09:31:31','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 09:31:31','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 09:40:00','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 09:40:00','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 16:42:03','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 16:42:03','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 16:42:03','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 16:45:03','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 16:45:03','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 18:00:03','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 18:00:03','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'Humpty Dumpty',TO_DATE('21/07/2016 18:00:03','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'ABC',TO_DATE('21/07/2016 18:00:03','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'ABC',TO_DATE('21/07/2016 18:10:03','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'ABC',TO_DATE('21/07/2016 18:50:03','DD/MM/YYYY HH24:MI:SS') FROM DUAL UNION ALL
   SELECT 'ABC',TO_DATE('21/07/2016 18:51:03','DD/MM/YYYY HH24:MI:SS') FROM DUAL
 )
SELECT
 name
,TO_CHAR(start_time,'DD/MM/YYYY HH24:MI:SS')     start_time
,TO_CHAR(end_time,'DD/MM/YYYY HH24:MI:SS')       end_time
FROM
 --Query B
 (SELECT
   name
  ,date2                                      start_time
  ,LEAD(date2) OVER (PARTITION BY name,TRUNC(date2) ORDER BY date2)   end_time
  ,start_flag
  FROM
   --Query A
   (SELECT
     name
    ,date2
    ,CASE
      WHEN date2 - LAG(date2) OVER (PARTITION BY name, TRUNC(date2) ORDER BY date2) <= (1/48)
       THEN 'N'
      ELSE 'Y'
     END                                        start_flag
    ,CASE
      WHEN LEAD(date2) OVER (PARTITION BY name, TRUNC(date2) ORDER BY date2) - date2 <= (1/48)
       THEN 'N'
      ELSE 'Y'
     END                                        end_flag
    FROM
     test_data
    ORDER BY
     name
    ,date2
   )
  WHERE 1=1
  AND (start_flag = 'Y' OR end_flag = 'Y')
  )
WHERE start_flag = 'Y'
;

【讨论】:

  • 谢谢克里斯蒂安,我已经编写了查询以及用于触摸的案例语句,但由于某种原因,(示例数据)第一个值不包括在内,我得到的开始时间是 09:31: 31 和结束时间为 16:42:03..
  • 下面戈登的回答是一个更好的答案,所以我给了它一个加分
猜你喜欢
  • 2022-11-25
  • 2018-04-17
  • 2023-02-02
  • 2023-03-12
  • 2020-11-22
  • 2014-08-20
  • 1970-01-01
  • 2023-03-23
  • 2018-06-14
相关资源
最近更新 更多