【问题标题】:Adding column to select statement brings in all historical data向 select 语句添加列会引入所有历史数据
【发布时间】:2019-07-24 02:12:52
【问题描述】:

大家晚上好!

我遇到了一个非常奇怪的问题,我无法理解。

我有 3 个表(零件表、零件移动历史记录和零件详细信息表)。

我要做的是让结果集返回批次#、零件#、产品描述、数量、零件位置、当前库存(相对于完整历史记录)以及上次移动产品的人。

现在,查询。当我运行以下查询时,我得到 4,751 行的结果集;这完全符合我的预期结果。但是,当我尝试添加用户 ID 字段时,我得到的结果集为 186,573。这个大型结果集似乎提取了所有历史数据,而不是仅将用户 ID 与我实际需要的 4,751 行进行匹配。

来自我需要的零件表 (prod_desc) 从我需要的零件详细信息表中(批次,零件#,批次数量,prtlocation) 从我需要的部件移动历史表中 (move_date,user_id)

4,751 个查询:

SELECT DISTINCT
inv.lot,
inv.part#,
prt.prod_desc,
inv.lotquantity,
inv.prtlocation,
MAX(mv.move_date)AS 'Move Date'
FROM invdet AS inv
LEFT JOIN movetable AS mv ON inv.part# = mv.part#
LEFT JOIN partmstr AS prt ON inv.part# = prt.part#
WHERE inv.lot IS NOT NULL
GROUP BY inv.lot,inv.part#,prt.prod_desc,inv.lotquantity,inv.prtlocation
ORDER BY inv.prtlocation

186,573 个查询:

SELECT DISTINCT
inv.lot,
inv.part#,
prt.prod_desc,
inv.lotquantity,
inv.prtlocation,
MAX(mv.move_date)AS 'Move Date'
mv.user_id
FROM invdet AS inv
LEFT JOIN movetable AS mv ON inv.part# = mv.part#
LEFT JOIN partmstr AS prt ON inv.part# = prt.part#
WHERE inv.lot IS NOT NULL
GROUP BY inv.lot,inv.part#,prt.prod_desc,inv.lotquantity,inv.prtlocation,mv.user_id
ORDER BY inv.prtlocation

如果我不使用 MAX 函数,我不会获得当前库存,而是会在表中获得所有我不需要的结果。我还在学习,我的 GROUP BY 有很多不足之处,因为我还在纠结它(欢迎提出建议!)。我敢肯定有一个子查询我可以在这里的某个地方抛出,但我仍在弄清楚这些。非常感谢任何帮助!

【问题讨论】:

    标签: sql-server sql-server-2008 azure-data-studio


    【解决方案1】:

    我认为问题在于,当您从表可移动表中插入 mv.user_id 时,您会得到所有部件的动作,而不仅仅是日期为 max(mv.move_date) 的最后一个动作。 一种方法是删除左连接到可移动并使用可能像这样的交叉应用

    SELECT inv.lot,inv.part,prt.prod_desc,inv.lotquantity,inv.prtlocation,x.move_date,x.user_id
    FROM invdet AS inv
    CROSS APPLY(SELECT TOP 1
                 mv.user_id,mv.move_date
                FROM movetable mv
                WHERE inv.part=mv.part
                ORDER BY mv.move_date DESC) AS x
    LEFT JOIN partmstr AS prt ON inv.part=prt.part
    WHERE inv.lot IS NOT NULL
    ORDER BY inv.prtlocation
    

    我没有测试过,但应该没问题,可能有点慢,因为交叉应用对 inv 表中的每一行执行一个子查询。如果太慢,可以使用ROWNUMBER创建一个只包含最后一个动作的表,然后在LEFT JOIN中使用,如下

    SELECT inv.lot,inv.part,prt.prod_desc,inv.lotquantity,inv.prtlocation,y.move_date,y.user_id
    FROM invdet AS inv
    LEFT JOIN(SELECT x.user_id,x.move_date,x.part
              FROM (SELECT mv.user_id,mv.move_date,mv.part,rn=ROWNUMBER() OVER(PARTITION BY mv.part ORDER BY mv.move_date DESC)
                    FROM movetable mv) AS x
              WHERE x.rn=1) AS y ON y.part=inv.part
    LEFT JOIN partmstr AS prt ON inv.part=prt.part
    WHERE inv.lot IS NOT NULL
    ORDER BY inv.prtlocation
    

    希望对你有帮助。

    【讨论】:

    • CROSS APPLY 成功了!非常感谢。我以前从未使用过 CROSS APPLY,所以我必须对此和 ROWNUMBER 进行一些研究才能真正了解它在做什么。再次感谢您!
    猜你喜欢
    • 2020-10-15
    • 2013-12-25
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 2022-11-20
    相关资源
    最近更新 更多