代码之家  ›  专栏  ›  技术社区  ›  THEn

用SQL查询检查序列

  •  2
  • THEn  · 技术社区  · 15 年前

    我有一张桌上订单,可以保存我们所有商店的所有订单。 我编写了一个查询来检查每个商店的顺序订单。 看起来像那样。

    select WebStoreID, min(webordernumber), max(webordernumber), count(webordernumber) 
    from orders
    where ordertype = 'WEB' 
    group by WebStoreID
    

    我可以查一下,所有的订单都有这个查询。web ordernumber是1到n之间的数字。

    如何在不加入临时/不同表的情况下编写查询来查找缺少的订单?

    4 回复  |  直到 14 年前
        1
  •  6
  •   Andomar    15 年前

    可以将表本身联接起来以检测没有前一行的行:

    select cur.*
    from orders cur
    left join orders prev 
        on cur.webordernumber = prev.webordernumber + 1
        and cur.webstoreid = prev.webstoreid
    where cur.webordernumber <> 1
    and prev.webordernumer is null
    

    这将检测1…n序列中的间隙,但不会检测重复项。

        2
  •  4
  •   Alex Martelli    15 年前

    我将生成一个“从1到n的所有整数”的辅助表(参见 http://www.sql-server-helper.com/functions/integer-table.aspx 对于某些使用SQL Server函数的方法,但由于这是您需要的东西,我会将它变成一个真正的表,而且对于任何SQL引擎,很容易做到这一点,只需一次),然后使用嵌套查询, SELECT value FROM integers WHERE value NOT IN (SELECT webordernumber FROM orders) &C。另请参见 http://www.sqlmag.com/Article/ArticleID/99797/sql_server_99797.html 对于类似于您的问题,“检测数字序列中的间隙”。

        3
  •  2
  •   Tom Warfield    14 年前

    如果您有rank()函数,但没有lag()函数(换句话说,SQL Server),则可以使用它(由 http://www.sqlmonster.com/Uwe/Forum.aspx/sql-server-programming/10594/Return-gaps-in-a-sequence ):

    create table test_gaps_in_sequence (x int)
    insert into test_gaps_in_sequence values ( 1 )
    insert into test_gaps_in_sequence values ( 2 )
    insert into test_gaps_in_sequence values ( 4 )
    insert into test_gaps_in_sequence values ( 5 )
    insert into test_gaps_in_sequence values ( 8 )
    insert into test_gaps_in_sequence values ( 9 )
    insert into test_gaps_in_sequence values ( 12)
    insert into test_gaps_in_sequence values ( 13)
    insert into test_gaps_in_sequence values ( 14)
    insert into test_gaps_in_sequence values ( 29)
    

     select lower_bound
             , upper_bound
          from (select upper_bound
                     , rank () over (order by upper_bound) - 1 as upper_rank
                  from (SELECT x+n as upper_bound
                          from test_gaps_in_sequence
                             , (SELECT 0 n
                                UNION
                                SELECT -1
                               ) T
                         GROUP BY x+n
                        HAVING MAX(n) = -1
                        ) upper_1
                ) upper_2
             , (select lower_bound
                     , rank () over (order by lower_bound) as lower_rank
                  from (SELECT x+n as lower_bound
                          from test_gaps_in_sequence
                             , (SELECT 0 n
                                UNION
                                SELECT 1
                               ) T
                         GROUP BY x+n
                        HAVING MIN(n) = 1
                        ) lower_1
                ) lower_2
          where upper_2.upper_rank = lower_2.lower_rank
          order by lower_bound
    

    …或者,包括“外部限制”:

    select lower_bound
         , upper_bound
      from (select upper_bound
                 , rank () over (order by upper_bound) - 1 as upper_rank
              from (SELECT x+n as upper_bound
                      from test_gaps_in_sequence
                         , (SELECT 0 n
                            UNION
                            SELECT -1
                           ) T
                     GROUP BY x+n
                    HAVING MAX(n) = -1
                    ) upper_1
            ) upper_2
       full join (select lower_bound
                 , rank () over (order by lower_bound) as lower_rank
              from (SELECT x+n as lower_bound
                      from test_gaps_in_sequence
                         , (SELECT 0 n
                            UNION
                            SELECT 1
                           ) T
                     GROUP BY x+n
                    HAVING MIN(n) = 1
                    ) lower_1
            ) lower_2
       on upper_2.upper_rank  = lower_2.lower_rank
         order by coalesce (lower_bound, upper_bound)
    
        4
  •  1
  •   Tony Andrews    15 年前

    如果 您的数据库支持分析函数,然后您可以使用如下查询:

    select prev+1, curr-1 from
    ( select webordernumber curr,
             coalesce (lag(webordernumber) over (order by webordernumber), 0) prev
      from   orders
    )
    where prev != curr-1;
    

    输出将显示间隙,例如

    prev+1 curr-1
    ------ ------
         3      7
    

    这意味着数字3到7(包括7)丢失了。