【问题标题】:Checking sequence with SQL query使用 SQL 查询检查序列
【发布时间】:2009-04-29 15:06:01
【问题描述】:

我有一张订单表,用于保存我们所有商店的所有订单。 我写了一个查询来检查每个商店的顺序订单。 看起来是这样的。

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

我可以通过此查询检查所有订单是否存在。 web ordernumber 是从 1...n 开始的数字。

如何在不加入临时/不同表的情况下编写查询以查找丢失的订单?

【问题讨论】:

  • 很难选择实际上不存在的数据。
  • 从 cmets 可以清楚地看出,您在此处针对 SQL Server 运行。你真的应该在你的问题中说出来,或者使用标签来表示它([SQL] 是 SQL 问题的通用标签,而不是 SQL Server)。

标签: sql sql-server ms-access sequence


【解决方案1】:

您可以自行加入表以检测没有前一行的行:

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 序列中的间隙,但不会检测重复。

【讨论】:

  • 可能想要显示:SELECT cur.webordernumber + 1 AS Missing_OrderNumber, cur.* from ... 对于以下序列:101、102、105 - 只有 103 会显示缺失。不确定显示 104 是否也很重要。
【解决方案2】:

我会制作一个“从 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】:

    如果你有 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】:

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

      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 (含)。

      【讨论】:

      • 谢谢。什么是nvl?我在 MSSQL 上找不到它?
      • 对不起,我在误解这是一个 Oracle 问题的情况下写了我的答案 - NVL 是 Oracle 为 COALESCE 代言。我已经更新了使用 COALESCE 的答案(如果你没有,它相当于 CASE WHEN param1 IS NOT NULL THEN param1 ELSE param2 END)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-17
      • 2023-04-02
      • 2016-07-14
      • 1970-01-01
      • 2015-05-03
      • 2010-11-06
      相关资源
      最近更新 更多