【问题标题】:Sql query to find items that had n consecutive failed attemptsSql 查询查找有 n 次连续尝试失败的项目
【发布时间】:2014-09-30 08:52:16
【问题描述】:

由于我的 sql 技能非常有限,我只发现了一些稍微不同的示例,我无法适应我的需求。

我有一个包含 3 个相关列的表格:

ItemID  Date      Result
1       1.2.2014  A
5       6.4.2014  B
9       7.4.2014  A
1       8.4.2014  A
1       9.4.2014  A
1       10.4.2014 A

我想找到连续 3 次具有特定结果(比如说 A)的项目。在上面的示例中,它将是第 1 项。日期通常不是连续的。

它应该在 Oracle SQL 中工作。

非常感谢您的帮助!

【问题讨论】:

  • 连续3次基于什么?日期和结果组合?有没有关键列?
  • 感谢您的帮助。我想过滤具有特定结果的项目,让我们及时说“A”。因此,如果第 1 项的结果是 A,然后是 B,然后是 A,然后是 A,则它不会被包括在内。仅当它有 A,然后是 A,然后是 A。日期可以是任何时间,而不是每天或每周或每月。只有顺序很重要。我希望我现在解释得足够好。没有键列。

标签: sql oracle find-occurrences


【解决方案1】:
SQL> WITH DATA AS(
  2  SELECT 1 ITEM_ID, TO_DATE('1.2.2014','DD.MM.YYYY') DT, 'A' RSLT FROM DUAL UNION ALL
  3  SELECT 5,       TO_DATE('6.4.2014','DD.MM.YYYY')  , 'B' RSLT FROM DUAL UNION ALL
  4  SELECT 9,       TO_DATE('7.4.2014','DD.MM.YYYY')  , 'A' RSLT FROM DUAL UNION ALL
  5  SELECT 1,       TO_DATE('8.4.2014','DD.MM.YYYY')  , 'A' RSLT FROM DUAL UNION ALL
  6  SELECT 1,       TO_DATE('9.4.2014','DD.MM.YYYY')  , 'A' RSLT FROM DUAL UNION ALL
  7  SELECT 1,       TO_DATE('10.4.2014','DD.MM.YYYY') , 'A' RSLT FROM DUAL)
  8  SELECT ITEM_ID FROM(
  9  SELECT A.*, ROW_NUMBER() OVER(PARTITION BY ITEM_ID ORDER BY RSLT) RN
 10  FROM DATA A)
 11  WHERE RN =3
 12  /

   ITEM_ID
----------
         1

SQL>

【讨论】:

    【解决方案2】:

    不确定这是否是实现它的最佳方法,但它确实有效。我创建了下表来将您的示例数据放入:

    CREATE TABLE DATE_RESULT(
      ITEM_ID INT,
      DATE_COL DATE,
      RESULT_COL VARCHAR2(255 CHAR)
    );
    

    然后运行这个查询:

    SELECT ITEM_ID FROM(
      SELECT
        ITEM_ID,
        TO_CHAR(DATE_COL,'DD-MON-YYYY') AS DATE_COL,
        RESULT_COL,
        LAG(ITEM_ID,1,NULL) OVER (ORDER BY ITEM_ID ASC, DATE_COL ASC) AS LAST_ITEM_ID,
        LAG(ITEM_ID,2,NULL) OVER (ORDER BY ITEM_ID ASC, DATE_COL ASC) AS LAST_ITEM_ID2,
        LAG(TO_CHAR(DATE_COL,'DD-MON-YYYY'),1,NULL) OVER (ORDER BY ITEM_ID ASC, DATE_COL ASC) AS LAST_DATE,
        LAG(TO_CHAR(DATE_COL,'DD-MON-YYYY'),2,NULL) OVER (ORDER BY ITEM_ID ASC, DATE_COL ASC) AS LAST_DATE2,
        LAG(RESULT_COL,1,NULL) OVER (ORDER BY ITEM_ID ASC, DATE_COL ASC) AS LAST_RESULT,
        LAG(RESULT_COL,2,NULL) OVER (ORDER BY ITEM_ID ASC, DATE_COL ASC) AS LAST_RESULT2
      FROM 
        DATE_RESULT
    )
    WHERE 
      ITEM_ID = LAST_ITEM_ID
      AND ITEM_ID = LAST_ITEM_ID2
      AND TO_DATE(DATE_COL)-1 = TO_DATE(LAST_DATE)
      AND TO_DATE(DATE_COL)-2 = TO_DATE(LAST_DATE2)
      AND RESULT_COL = LAST_RESULT
      AND RESULT_COL = LAST_RESULT2;
    

    查询使用 Oracle 的 LAG() 函数从之前的行中获取值。所以在本例中,LAST_ITEM_ID 是前一行的商品 ID,LAST_ITEM_ID 是前两行的商品 ID。

    在 WHERE 子句中,我确保 ITEM_ID 与前两个 ITEM_ID 匹配,并且 RESULT_COL 与前两个 RESULT_COL 匹配。我还要确保最后两个日期是连续的。

    【讨论】:

    • 很抱歉没有很好地描述我想做的事情。这已经非常接近了。但我正在寻找具有特定结果的项目,假设“x”连续出现 3 次。日期可以是任何时间,中间只需要有“x”之外的其他事件。 Lag() 似乎是正确的方法。我会看看我是否可以提取这个的意思。非常感谢!
    【解决方案3】:

    感谢 user1578653,我想通了。也许有一种更优雅的方法可以做到这一点,但它在几秒钟内就可以处理大约 500000 条记录:

    SELECT ITEM_ID FROM(
       SELECT ITEM_ID, DATECOL, RESULT,
         LAG(ITEM_ID,1,NULL) OVER (ORDER BY ITEM_ID ASC, DATECOL ASC) AS LASTITEM,
         LAG(ITEM_ID,2,NULL) OVER (ORDER BY ITEM_ID ASC, DATECOL ASC) AS LASTITEM2,
         LAG(RESULT,1,NULL) OVER (ORDER BY ITEM_ID ASC, DATECOL ASC) AS LASTCODE,
         LAG(RESULT,2,NULL) OVER (ORDER BY ITEM_ID ASC, DATECOL ASC) AS LASTCODE2
       FROM
         RESULTTABLE
       )
    WHERE
       ITEM_ID = LASTITEM
       AND ITEM_ID = LASTITEM2
       AND RESULT = 'A'
       AND RESULT = LASTCODE
       AND RESULT = LASTCODE2;
    

    我正在寻找在此示例中连续出现 3 次的“A”结果。

    我很高兴,谢谢!

    【讨论】:

      猜你喜欢
      • 2019-02-16
      • 1970-01-01
      • 2020-06-25
      • 2016-02-13
      • 1970-01-01
      • 2022-01-01
      • 2013-06-01
      • 2021-09-16
      • 2019-02-25
      相关资源
      最近更新 更多