没有子查询的主/子项目行号选择

时间:2019-04-09 17:18:42

标签: sql sql-server

因此,我正在查看一个名为LINEITEM的表,该表列出了“主/组件”排列中的几个项目编号。他们称它们为工具包。套件的想法是,套件中可以包含任意数量的子项目。这是一个简单的示例:

+----------+---------+---------+----------+-----------------+
| ORDER_NO | ITEM_ID | LINE_NO | KIT_FLAG | KIT_MASTER_LINE |
+----------+---------+---------+----------+-----------------+
|   858710 |   15291 |       1 | Y        |               0 |
|   858710 |     113 |       2 | K        |               1 |
|   858710 |   15279 |       3 | K        |               1 |
|   858710 |   15292 |       4 | K        |               1 |
|   858710 |   15321 |       5 | Y        |               0 |
|   858710 |     106 |       6 | K        |               5 |
|   858710 |   15563 |       7 | K        |               5 |
|   858710 |   15564 |       8 | K        |               5 |
|   858710 |   15296 |       9 | Y        |               0 |
|   858710 |     116 |      10 | K        |               9 |
|   858710 |   15479 |      11 | K        |               9 |
|   858710 |   15480 |      12 | K        |               9 |
+----------+---------+---------+----------+-----------------+

因此,订购858710共有3个套件。第1行是套件“ master”,在KIT_FLAG中具有值“ Y”,在第2、3和4行中,该套件中的所有组件的值均为“ K”。直到我们到达5号线,这里已经声明了第二个套件,其中6号,7号和8号线是它的组成部分。

我需要在每个子项目上显示哪个行项目是它所属的“套件主文件”。

我想要的输出是KIT_MASTER_LINE列中当前显示的输出。我什至可以使用子查询来完成此操作:

SELECT ORDER_NO, ITEM_ID, LINE_NO, KIT_FLAG,
ISNULL((
    SELECT MAX(LINE_NO)
    FROM LINEITEM AS l2
    WHERE 
        l2.LINE_NO < li.LINE_NO
        AND li.KIT_FLAG = 'K'
        AND l2.KIT_FLAG = 'Y'
        AND l2.ORDER_NO = li.ORDER_NO
), 0) AS 'KIT_MASTER_LINE'
FROM LINEITEM li
ORDER BY LINE_NO

...但是,执行计划并非很糟糕,并且扫描大型表需要花费很多时间。

我想我很好奇是否有使用窗口函数或类似函数执行此操作的更好方法。不得不两次调用LINEITEM表的这种困扰使我原本费力的快速过程及其所有优化都被破坏了。

我非常感谢您的见解。

1 个答案:

答案 0 :(得分:0)

我最终能够通过从行号中减去旋转计数来寻求解决方案。没有相关的子查询,可在几秒钟内运行。哇!

SELECT *,
CASE WHEN KIT_FLAG = 'K'
    THEN LINE_NO - ROW_NUMBER() OVER (PARTITION BY KIT_FLAG, [Group] ORDER BY LINE_NO)
    ELSE 0
END AS 'KIT_MASTER_LINE'
FROM (
    SELECT ORDER_NO, ITEM_ID, LINE_NO, KIT_FLAG, 
    ROW_NUMBER() OVER (ORDER BY ORDER_NO, LINE_NO) - ROW_NUMBER() OVER (PARTITION BY KIT_FLAG ORDER BY ORDER_NO, LINE_NO) AS [Group]
    FROM LINEITEM
) AS [GroupTable]
ORDER BY ORDER_NO, LINE_NO