选择上一行和下一个匹配行或最后一行之间的行

时间:2009-12-29 15:48:05

标签: tsql stored-procedures select join

这可能是一个问题,或者我可能会立刻问过多:

坚果壳
如何在两次出现的“B / O INFO%'之类的描述或'B / O INFO%'之间以及给定订单号的最后一行(WHERE OrderNo = 12345678)之间从表中选择行

背景
我正在尝试为我们的业务客户整理一份未结订单行项目报告。数据库我正在使用旧的,但“尝试和真实”及其设计和写入它的进程应该被认为是不可变的,以回答这个问题(主要是因为将数据写入此表的过程很难处理Unisys大型机上的{COBOL,MSSQL复制的大型机,没有完全合格的Unisys大型机COBOL程序员,移动关闭大型机等}。)。

我现在试图完成2周的工作是创建一个SELECT语句,该语句返回订单和订单行项目的层次结构。此层次结构表示由我们的客户和所有衍生的“子”订单发出的订单,这些订单试图从“根”订单填充(全部或部分)订单项。

下订单时,会对其应用许多自动和手动流程。如果系统看到订单行项目可以通过从不同仓库发货来完全履行,则它将为这些订单项创建新的子订单。如果订单项数量不可用,则会部分发货并为剩余部分创建延期交货。如果客户确实需要订单项,则人工将手动创建从不同位置采购订单的新订单。

问题
令人沮丧的情况是非索引的char(21)列用于声明子订单中的哪些订单项适用于给定的父订单,并且该链接信息与订购的实际产品不在同一行 - 它是完全独立的“评论”行。我遇到的真正麻烦的是尝试从这些子订单中选择特定的订单行项目。最麻烦的是在匹配描述模式的两个实例或订单行的结尾之间选择订单行

我已经尝试了各种各样的JOIN和WHERE等等。我不是DBA,但是我已经远远高于“知道足够危险”的水平而且我已经达到理解的目的。这一起。

我需要/想做什么
创建一个存储过程,返回所有订单号的结果集及其在订单层次结构中的相应项目编号,然后我可以使用它来确定根订单的订单项的数量履行。

详情
子订单中这些注释行与父母的关系如下:

  1. 以“@ ??? /”开头的说明表示已创建子订单(请参阅下面的#2),订单号与斜杠之间的数字相匹配。
  2. 以“MEO INFO”开头的说明表示订单中的所有项目(请参阅上面的#1)与与说明的数字部分相匹配的订单相关。
  3. 以“* S /”开头的说明表示已创建子订单(请参阅下面的#4),订单号与斜杠之间的数字相匹配。
  4. 以“B / O#”开头的描述表示上面的行与匹配描述的数字部分的顺序相关。 (见上文#3)
  5. 以“B / O INFO”开头的说明是指下一次出现“B / O INFO”之前至少有一行,或者订单行项目的结尾与匹配说明的数字部分的订单相关。父母将不会引用此子订单。
    • 包含诸如“B / O#”或“B / O INFO”之类的行注释的订单可以是从一个或多个父订单履行订单行项目的“复合”子订单。相关订单项,详见上表。
    • 在订单中查找“@ ??? /”和“* S /”行很容易引用子订单。

    使用此示例数据,根顺序号为12345678,我需要构建所有相关子行项目的层次结构。
    示例数据

    OrderNo |ItemNo |Description   |LineCD
    -------------------------------------------------
    Lines pointing to child orders
    12345678 1  @LVL/11223344/001
    12345678 2  *S/11335577/12345ELEM
    
    All lines relevant to parent order
    11223344 1  MEO INFO 12345678
    11223344 2  RAIL
    11223344 3  BODY OVEN WELD ASM
    
    Comment lines indicate above line is for a parent order
    55667788 1  PUMP&MOTOR
    55667788 2  B/O #  12345678      
    55667788 3  *S/22446688/12345GLAS
    55667788 4  B/O #  77553311 //The above line is NOT related to 12345678
    
    Comment lines indicating line(s) below until end of lines or
    next comment are for a parent order
    98765432 31  B/O INFO 12345678  C
    98765432 32  CNTRL-ELEC
    98765432 33  STRIKE
    98765432 34  CONTROL-ELECTRICAL
    98765432 35  B/O INFO 88664422  C
    

    我希望这个问题是可以回答的。如果没有,它至少会让你的大脑得到很好的锻炼。

2 个答案:

答案 0 :(得分:0)

哇,真是一团糟。

虽然我讨厌推荐使用游标,但我没有看到任何其他方法来获取您想要的数据。我不认为基于标准集的操作(选择加入等)会在任何合理的事情中提取数据。

这给我们留下了3个潜在的解决方案。

一,在代码中进行处理。这有许多明显的缺点,具体取决于数据集的大小。

二,使用游标进行处理。游标的性能不是很好,但是以这种方式构建数据,性能甚至不在人们的视线中。

三,使用某种类型的基于CLR的解决方案。这里的缺点是你能够安装它以及你的sql server是否支持它。

祝你好运。

答案 1 :(得分:0)

这是非常复杂的,我不确定我是否完全理解它,但我认为好的输出看起来像:

ParentID ChildID ItemNo Description(作为结果集)

所有B / O,B / O INFO和S /转换为父/子关系,父ID为空订单。这需要在单次通过源表的过程中在内存中构建一个订单行(和关系)表。

如果在内存中构建它是不可接受的,并且您遇到性能问题,我建议您考虑输出这个单个结果集,而不是两遍:

ChildID ItemNo Description(过滤掉S / B / O B / O INFO)

UNION

ChildID ItemNo Description(ItemNo始终为零,描述设置为ParentID)

如果 将结果暂时放在某个地方,那么它应该放在另一个表空间中。

验证结果集输出的使用者中的父子关系(例如Excel或DSS包)。

这种方式至少发生了一些翻译/压缩/合理化,网络使用减少了,关键字段也不那么好,模糊不清。这个可能是一个更好的解决方案,但从问题中不清楚优先级和问题是什么。

这听起来很像现实生活。优雅(甚至可能是推荐)的免费解决方案。

修改

可能比我建议将网络耗尽更难。

在双程解决方案中,我建议给出B / O子部分,如

97387326(在B / O或B / O INFO部分之前)

97387326-1(第一个B / O或B / O INFO部分的一部分)

97387326-2(第二个B / O或B / O INFO部分的一部分)

(等)