使用SQL查询检查序列
-
03-07-2019 - |
题
我有一个表订单,可以保存我们所有商店的所有订单。 我写了一个查询来检查每个商店的序列顺序。 它看起来像那样。
select WebStoreID, min(webordernumber), max(webordernumber), count(webordernumber)
from orders
where ordertype = 'WEB'
group by WebStoreID
我可以查看此查询中是否存在所有订单。 web ordernumber是1 ... n。
中的数字如何在不加入临时/不同表的情况下编写查询以查找丢失的订单?
解决方案
您可以将表连接到自身以检测没有前一行的行:
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序列中的间隙,但不会检测到重复。
其他提示
我会创建一个“从1到n的所有整数”的辅助表。 (参见 http://www.sql-server-helper.com/函数/ integer-table.aspx 用于某些方法来使用SQL Server函数,但是因为它是你需要反复使用的东西,所以无论如何我都会把它变成一个真正的表,并且使用任何SQL引擎它很容易做到,只需一次)然后使用嵌套查询, SELECT值FROM整数WHERE值NOT IN(SELECT webordernumber FROM orders)
&amp; c。另请参阅 http://www.sqlmag.com/Article/ArticleID/99797/ sql_server_99797.html 针对与您类似的问题,“检测一系列数字中的差距”。
如果你有rank()函数而不是lag()函数(换句话说,SQL Server),你可以使用它(由 http://www.sqlmonster.com/Uwe/Forum.aspx/sql-server-programming / 10594 /返回隙-IN-A-序列):
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)
如果您的数据库支持分析函数,那么您可以使用如下查询:
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号的数字。
不隶属于 StackOverflow