【问题标题】:SQL query for last consecutive same data最后连续相同数据的 SQL 查询
【发布时间】:2017-06-01 09:16:43
【问题描述】:

我的表格中有数据

+----+------------+------+
| Id | data_date  | data |
+----+------------+------+
|  1 | 01/01/2017 |    1 |
|  1 | 01/02/2017 |    0 |
|  1 | 01/03/2017 |    0 |
|  1 | 01/04/2017 |    0 |
|  2 | 01/02/2017 |    0 |
|  2 | 01/03/2017 |    0 |
|  2 | 01/04/2017 |    1 |
|  2 | 01/05/2017 |    1 |
+----+------------+------+

数据列只有值 0 和 1

如何获取最后几天连续相同的数据类型,即每个 ID 的“0”或“1”

+----+-----------+-----------------+
| Id | data_Type | Last_Data_Count |
+----+-----------+-----------------+
|  1 |         0 |               3 |
|  2 |         1 |               2 |
+----+-----------+-----------------+

【问题讨论】:

  • 您使用的是 MySQL 还是 Oracle?
  • @TimBiegeleisen 这有什么不同吗?
  • 是的,RDBMS 有所作为。日期之间是否有间隔是否重要?
  • 这有很大的不同,因为你的问题闻起来像一个间隙和孤岛问题。 MySQL 没有(内置)分析功能,因此使用 MySQL 可能比使用 Oracle 更难。
  • 为什么不坚持使用普通的 ANSI SQL?

标签: mysql sql oracle


【解决方案1】:

Oracle 查询

SELECT id,
       MAX( last_data ) AS data_type, 
       COUNT(*) AS last_data_count
FROM   (
  SELECT d.*,
         MAX ( CASE WHEN data <> last_data THEN data_date END )
           OVER ( PARTITION BY id ) AS last_date
  FROM   (
    SELECT d.*,
           MAX( data ) KEEP ( DENSE_RANK LAST ORDER BY data_date )
             OVER ( PARTITION BY id ) AS last_data
    FROM   data d
  ) d
)
WHERE  data_date > last_date
GROUP BY id;

【讨论】:

    【解决方案2】:

    假设您需要每个iddata 计数max(data_date),您可以试试这个。它应该适用于几乎所有的 RDBMS。

    Rexter Sample for MYSQL

    select t3.id
        ,max(data) as data_type
        ,count(data) as last_data_count
        from table t3
        where exists
            (select 1 from Table t1
                where exists  
                (select 1 from table t2
                 where t1.id=t2.id
                 group by t2.id
                 having t1.data_date=max(t2.data_date)
                 ) 
         and t1.id=t3.id and t1.data=t3.data
    )
    group by t3.id
    ;
    

    解释:内部exists 用于根据max(date) 获取每个id 的最后data_date。现在要获取计数,我使用外部 exists 来匹配 iddata,然后使用 group by id 来获取计数。

    【讨论】:

    • 我不知道 Rextester 似乎是一个很棒的工具,谢谢
    【解决方案3】:

    这可以很容易地在 Oracle 中通过使用Tabibitosan 然后对结果进行分组,就像这样(注意:我假设您的意思是“最后几天连续”是指连续的行,不是连续的日期):

    WITH sample_data AS (SELECT 1 ID, to_date('01/01/2017', 'dd/mm/yyyy') data_date, 1 DATA FROM dual UNION ALL
                         SELECT 1 ID, to_date('01/02/2017', 'dd/mm/yyyy') data_date, 0 DATA FROM dual UNION ALL
                         SELECT 1 ID, to_date('01/03/2017', 'dd/mm/yyyy') data_date, 0 DATA FROM dual UNION ALL
                         SELECT 1 ID, to_date('01/04/2017', 'dd/mm/yyyy') data_date, 0 DATA FROM dual UNION ALL
                         SELECT 2 ID, to_date('01/01/2017', 'dd/mm/yyyy') data_date, 0 DATA FROM dual UNION ALL
                         SELECT 2 ID, to_date('01/02/2017', 'dd/mm/yyyy') data_date, 0 DATA FROM dual UNION ALL
                         SELECT 2 ID, to_date('01/03/2017', 'dd/mm/yyyy') data_date, 1 DATA FROM dual UNION ALL
                         SELECT 2 ID, to_date('01/04/2017', 'dd/mm/yyyy') data_date, 1 DATA FROM dual UNION ALL
                         SELECT 3 ID, to_date('01/01/2017', 'dd/mm/yyyy') data_date, 0 DATA FROM dual UNION ALL
                         SELECT 3 ID, to_date('01/02/2017', 'dd/mm/yyyy') data_date, 1 DATA FROM dual UNION ALL
                         SELECT 3 ID, to_date('01/03/2017', 'dd/mm/yyyy') data_date, 0 DATA FROM dual UNION ALL
                         SELECT 3 ID, to_date('01/05/2017', 'dd/mm/yyyy') data_date, 0 DATA FROM dual)
    -- end of mimicking data in a table called "sample_data"
    -- see below for the main SQL query:
    SELECT ID,
           DATA,
           COUNT(*) last_data_count
    FROM   (SELECT ID,
                   data_date,
                   DATA,
                   MAX(data_date) OVER (PARTITION BY ID) max_data_date,
                   row_number() OVER (PARTITION BY ID ORDER BY data_date)
                     - row_number() OVER (PARTITION BY ID, DATA ORDER BY data_date) grp
            FROM   sample_data)
    GROUP BY ID,
             DATA,
             grp,
             max_data_date
    HAVING   max_data_date = MAX(data_date);
    
            ID       DATA LAST_DATA_COUNT
    ---------- ---------- ---------------
             1          0               3
             2          1               2
             3          0               2
    

    tabibitosan 部分(即row_number() over (&lt;overall set of data&gt;) - row_number() over (&lt;subset of data&gt;))为具有数据列中的相同值。

    获得此信息后,很容易找到每组连续行的计数。但是,由于您在最新计数之后,我使用MAX() 分析函数来查找每个id 的最新data_date。

    然后,我们可以比较每组连续行的最大 data_date,并使用它来查找与 id 的最大 data_date 匹配的连续行集(我们在 having 子句中执行此操作)。瞧!

    【讨论】:

    • 感谢 Boneist 的解释和询问,这真的很有帮助,也感谢其他所有人,顺便说一句,我正在使用 oracle。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-25
    • 1970-01-01
    • 1970-01-01
    • 2022-07-19
    • 2020-10-25
    • 2020-12-20
    • 1970-01-01
    相关资源
    最近更新 更多