1

有一个包含以下字段的表:

顺序、组、序列

要求给定组中的所有订单形成连续序列。例如:1,2,3,4 或 4,5,6,7。如何使用单个 SQL 查询检查哪些订单不符合此规则?谢谢你。

Example data:

Order   Group   Sequence
1   1   3
2   1   4
3   1   5
4   1   6
5   2   3
6   2   4
7   2   6

Expected result:
Order
5
6
7

如果查询仅返回具有错误序列的组,则也接受,示例数据为 2。

4

6 回答 6

4

假设生成了序列,因此不能复制:


SELECT group
 FROM theTable
 GROUP BY group
 HAVING MAX(Sequence) - MIN(Sequence) <> (COUNT(*) - 1);

于 2009-05-18T09:29:40.923 回答
2

我个人认为我会考虑重新考虑要求。关系数据库的本质是,由于记录回滚,序列中的间隙很容易出现。例如,假设一个订单开始在其中创建四个项目,但一个因某种原因而失败并被回滚。如果您手动预先计算序列,那么您将有一个间隙,即回滚的序列不是最后一个。在其他情况下,由于多个用户几乎同时查找序列值,或者如果客户在最后一分钟从订单中删除了一条记录,您可能会遇到间隙。老实说,您希望从父子关系中无法获得的连续序列中获得什么?

于 2009-05-18T17:53:04.603 回答
2

这个怎么样?

从具有计数(序列)<=最大(序列)-最小(序列)
的组中选择组

[编辑] 这假设 Sequence 不允许在特定组内重复。最好使用:
count != max - min + 1

[再次编辑] D'oh,仍然不完美。不过,另一个清除重复项的查询会解决这个问题。

[编辑最后一个] 原始查询在 sqlite 中运行良好,这是我可用于快速测试的。它比 SQL Server 宽容得多。感谢贝尔的指点。

于 2009-05-18T09:22:45.507 回答
1

此 SQL 选择没有连续序列的订单 3 和 4。

DECLARE @Orders TABLE ([Order] INTEGER, [Group] INTEGER, Sequence INTEGER)

INSERT INTO @Orders VALUES (1, 1, 0)
INSERT INTO @Orders VALUES (1, 2, 0)
INSERT INTO @Orders VALUES (1, 3, 0)

INSERT INTO @Orders VALUES (2, 4, 0)
INSERT INTO @Orders VALUES (2, 5, 0)
INSERT INTO @Orders VALUES (2, 6, 0)

INSERT INTO @Orders VALUES (3, 4, 0)
INSERT INTO @Orders VALUES (3, 6, 0)

INSERT INTO @Orders VALUES (4, 1, 0)
INSERT INTO @Orders VALUES (4, 2, 0)
INSERT INTO @Orders VALUES (4, 8, 0)

SELECT o1.[Order]
FROM @Orders o1
     LEFT OUTER JOIN @Orders o2 ON o2.[Order] = o1.[Order] AND o2.[Group] = o1.[Group] + 1
WHERE o2.[Order] IS NULL
GROUP BY o1.[Order]
HAVING COUNT(*) > 1
于 2009-05-18T09:28:31.033 回答
0

After a while I came up with the following solution. It seems to work but it is highly inefficient. Please add any improvement suggestions.

SELECT OrdMain.Order
  FROM ((Orders AS OrdMain
  LEFT OUTER JOIN Orders AS OrdPrev ON (OrdPrev.Group = OrdMain.Group) AND (OrdPrev.Sequence = OrdMain.Sequence - 1))
  LEFT OUTER JOIN Orders AS OrdNext ON (OrdNext.Group = OrdMain.Group) AND (OrdNext.Sequence = OrdMain.Sequence + 1))
WHERE ((OrdMain.Sequence < (SELECT MAX(Sequence) FROM Orders OrdMax WHERE (OrdMax.Group = OrdMain.Group))) AND (OrdNext.Order IS NULL)) OR
      ((OrdMain.Sequence > (SELECT MIN(Sequence) FROM Orders OrdMin WHERE (OrdMin.Group = OrdMain.Group))) AND (OrdPrev.Order IS NULL))
于 2009-05-18T10:44:08.947 回答
0

所以你的桌子是

Order Group Sequence
1     1     4
1     1     5
1     1     7

..你想知道 1,1,6 丢失了吗?

select
  min(Sequence) MinSequence, 
  max(Seqence) MaxSequence 
from 
  Orders 
group by 
  [Order], 
  [Group]

您可以找出给定订单和组的界限。

现在您可以使用特殊的数字表来模拟正确的数据,该表只包含您可以用于序列的每个数字。是这样一个数字表的一个很好的例子。如何创建它并不重要,您还可以创建一个包含从 x 到 y 的所有数字的 excel 文件并导入该 excel 表。

在我的示例中,我假设这样一个名为“Numbers”的数字表只有一列“n”:

select 
  [Order], 
  [Group], 
  n Sequence
from
  (select min(Sequence) MinSequence, max(Seqence) MaxSequence from [Table] group by [Order], [Group]) MinMaxSequence
  left join Numbers on n >= MinSequence and n <= MaxSequence

将该 SQL 放入新视图中。在我的示例中,我将调用视图“vwCorrectOrders”。

这为您提供了序列连续的数据。现在您可以将该数据与原始数据连接起来,以找出缺少哪些序列:

select 
  correctOrders.*
from
  vwCorrectOrders co 
  left join Orders o on 
      co.[Order] = o.[Order] 
  and co.[Group] = o.[Group]
  and co.Sequence = o.Sequence
where
  o.Sequence is null

应该给你

Order Group Sequence
1     1     6
于 2009-05-18T10:03:23.290 回答