【问题标题】:How to find/select consecutive records (occurring at least twice) in a table using SQL如何使用 SQL 在表中查找/选择连续记录(至少出现两次)
【发布时间】:2020-05-16 07:07:38
【问题描述】:

我有下表,里面有一些简单的数据。

Table sample
Product   Date                    Sold
 A        29-04-2020 12:23:44PM   Y
 A        30-04-2020 12:39:31AM   N
 A        01-05-2020 03:25:49PM   N
 A        02-05-2020 05:16:30PM   Y
 A        03-05-2020 11:11:51AM   N
 A        04-05-2020 12:39:31AM   N
 A        05-05-2020 12:20:40AM   Y
 A        06-05-2020 06:10:56AM   N
 A        07-05-2020 12:01:03PM   N
 A        08-05-2020 10:40:45AM   N
 A        09-05-2020 12:22:49AM   Y
 A        10-05-2020 12:01:12AM   Y
 A        11-05-2020 07:29:22PM   N
 A        12-05-2020 01:58:59AM   Y
 A        13-05-2020 10:21:47PM   Y

我需要做的就是返回 count(A),其中每个 Sold = 'N' 并且前一天也是 Sold = 'N'。时间也很重要,因为它需要选择前一天,而不仅仅是 DAY-24 小时。因此,即使“06-05-2020 06:10:56AM”已经超过 1 天,仍然会选择“07-05-2020 12:01:03PM”。

预期输出:(4) 示例:

Table sample
Product   Date                    Sold
 A        01-05-2020 03:25:49PM   N
 A        04-05-2020 12:39:31AM   N
 A        07-05-2020 12:01:03PM   N
 A        08-05-2020 10:40:45AM   N

我尝试过使用 2 个表:SELECT count(o1.product) FROM sample o1, sample o2 WHERE (o1.date >= o2.date-1) AND o1.sold = 'N' AND o2.sold = 'N' 但是这对我不起作用。

非常感谢任何帮助,谢谢。

【问题讨论】:

  • MySQL 还是 SQL Server?
  • 称我为愚蠢,但我不确定。我正在使用另一个程序来查询 SQL 数据库。我相信是 SQL Server

标签: sql sql-server date


【解决方案1】:

检查上一个 sold 是 'N' 并且上一个 date 是昨天的:

with cte as
 (
   select
      product
     ,date
     ,sold
     -- previous "sold"
     ,lag(sold) over (partition by product order by date) as prev_sold
     -- previous "date" truncating the time portion
     ,cast(lag(date) over (partition by product order by date) as date) as prev_date
   from myTable
 )
select *
from cte
where sold = 'N'
  and prev_sold = 'N'
  and cast(date as date)= dateadd(day, 1, prev_date)

【讨论】:

    【解决方案2】:

    虽然 dnoeth 有一个很好的解决方案,但你可以只用一个窗口函数来做到这一点:

    select *
    from (select t.*,
                 lag(date) over (partition by product, sold order by date) as prev_n_date
          from t
          where sold = 'N'
         ) t
    where convert(date, date) = dateadd(day, 1, convert(date, prev_n_date));
    

    这会查看上一个日期为“N”并检查它是否是前一天。

    Here 是一个 dbfiddle。

    注意:如果您每天有多行,这个逻辑会有点棘手。如果这是一个问题,请提出一个问题,并提供适当的样本数据、期望的结果以及在一天内处理多个值的逻辑解释。

    【讨论】:

    • 外部where sold = 'N'不需要了
    • @dnoeth 。 . .这是真的。谢谢。
    • 这是否会从原始数据库中修改/更新/删除任何内容?通过使用 partition/over /lag/convert ?抱歉,我现在只是查找这些运算符的定义。
    • @M.Owen 。 . . SELECT 语句不修改数据库。您需要 UPDATEDELETE 来执行此操作。
    【解决方案3】:

    以下应该在 SQL Server 和 MySQL 8 中,这里是 demo

    with cte as
    (
      select
          product,
          date,
          sold,
          lag(sold) over (partition by rnk order by date) as nrnk
      from
      (
        select
            *,
            dateadd(day, - row_number() over(order by date), date) as rnk
         from myTable
         where sold = 'N'
      ) val
    )
    
    select 
      product,
      date,
      sold
    from cte
    where nrnk = 'N'
    

    输出:

    ---------------------------
    | product  date      sold |
    --------------------------- 
    |  A     2020-05-01    N  |
    |  A     2020-05-04    N  |
    |  A     2020-05-07    N  |
    |  A     2020-05-08    N  |
    ---------------------------
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-20
      • 2014-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多