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

问题描述 投票:0回答:1

所以我正在寻找一个名为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表的挂断所破坏。

我很欣赏任何见解。

sql sql-server
1个回答
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
© www.soinside.com 2019 - 2024. All rights reserved.