【问题标题】:Return duration of an item from its transactions, many to many, SQL从其事务中返回一个项目的持续时间,多对多,SQL
【发布时间】:2020-10-05 13:45:20
【问题描述】:

希望我能得到一些帮助。

情况

有两个输入站和一个输出站。物品被扫描进出。我需要知道一件物品在车站里的时间。让我们将“站内”视为传入日期扫描和传出日期扫描之间的时间。

问题

  1. 一个项目可以(意外)多次扫描到任一站点(为此,我正在考虑确定是否在同一天(而不是查看小时数)进行了扫描,然后返回最早扫描的时间)

  2. 一个项目可以多次进出工作站(多次进出扫描)

  3. 如果一个项目被扫描到两个传入位置,需要获取最早时间

数据示例.. 我们开始

╔═════════╦════════╦══════════════════╦════════════════╦══════════╗
║ Row_num ║ ItemID ║      Dates       ║  LocationName  ║   Type   ║
╠═════════╬════════╬══════════════════╬════════════════╬══════════╣
║       1 ║ ItemA  ║ 1/7/20 12:49 PM  ║ Outgoing_Loc   ║ Outgoing ║
║       2 ║ ItemA  ║ 1/2/20 7:29 AM   ║ Incoming_Loc_A ║ Incoming ║
║       3 ║ ItemB  ║ 1/3/20 11:01 AM  ║ Outgoing_Loc   ║ Outgoing ║
║       4 ║ ItemB  ║ 1/2/20 4:57 PM   ║ Incoming_Loc_B ║ Incoming ║
║       5 ║ ItemB  ║ 1/2/20 5:01 PM   ║ Incoming_Loc_A ║ Incoming ║
║       6 ║ ItemB  ║ 12/12/19 5:58 PM ║ Outgoing_Loc   ║ Outgoing ║
║       7 ║ ItemB  ║ 12/12/19 5:57 PM ║ Outgoing_Loc   ║ Outgoing ║
║       8 ║ ItemB  ║ 5/20/19 10:19 AM ║ Outgoing_Loc   ║ Outgoing ║
║       9 ║ ItemC  ║ 1/9/20 9:20 AM   ║ Outgoing_Loc   ║ Outgoing ║
║      10 ║ ItemC  ║ 1/2/20 6:42 PM   ║ Incoming_Loc_A ║ Incoming ║
║      11 ║ ItemC  ║ 12/20/19 5:54 AM ║ Outgoing_Loc   ║ Outgoing ║
║      12 ║ ItemC  ║ 10/10/19 6:13 PM ║ Outgoing_Loc   ║ Outgoing ║
║      13 ║ ItemC  ║ 10/5/19 7:00 PM  ║ Incoming_Loc_A ║ Incoming ║
║      14 ║ ItemC  ║ 7/16/19 9:18 AM  ║ Outgoing_Loc   ║ Outgoing ║
╚═════════╩════════╩══════════════════╩════════════════╩══════════╝

我尝试将每种类型的问题都提供到分配给不同项目的表格中。

完美的交易是ItemA,它是如此简单和干净,如果它们都是这样,那么我可以加入表格并将它们拉到不同的列上。

ItemB,你会注意到这个被扫描到了两个传入的位置,但我只需要返回一个 - 它最早来自该批次。此外,需要返回最旧的传出(12/12/19)之后和最后一次传出(1/3/20)之前的传入。

ItemC,类似于 ItemB 的最后一条语句,该项目从位置进出两次。需要获取按时间顺序最有意义的传入和传出对。

我不知道解决这个问题有多难,但我很难找到解决方案。我不确定如何在传出之间挤入传入日期。

输出示例:
需要得到每个项目在车站的天数。如果该项目已多次进出,则需要按时间顺序配对最有意义的传入和传出。例如,ItemC 有多个传入和传出日期,但我只需要具有开头和结尾的日期作为一对。

+--------+-----------------+------------------+-----------------+
| ItemID |    Incoming     |     Outgoing     | Days in Station |
+--------+-----------------+------------------+-----------------+
| ItemA  | 1/2/20 7:29 AM  | 1/7/20 12:49 PM  | 5.00            |
| ItemB  | 1/2/20 4:57 PM  | 1/3/20 11:01 AM  | 1.00            |
| ItemC  | 1/2/20 6:42 PM  | 1/9/20 9:20 AM   | 7.00            |
| ItemC  | 10/5/19 7:00 PM | 10/10/19 6:13 PM | 5.00            |
+--------+-----------------+------------------+-----------------+

【问题讨论】:

  • “解决方案”是什么?你的问题是什么?交付物究竟是什么?如果是代码,究竟可以输入什么以及输出如何成为输出的函数? PS 使用足够多的单词、句子和对部分示例的引用来清楚完整地表达你的意思。在给出业务关系(船舶)/关联或表(基础或查询结果)时,说明其中的一行根据其列值说明了业务情况。你能做什么,它完成了什么?解释被卡住。代码问题请给minimal reproducible example
  • 除了@philipxy 所说的,我建议你包括预期的输出。
  • @philipxy 完全有效的积分。我编辑了帖子以包含一个输出示例

标签: sql sql-server date window-functions gaps-and-islands


【解决方案1】:

这是一个孤岛问题。一种方法是使用每个传入记录递增的累积总和来定义组,并将其用于聚合:

select
    itemID,
    min(dates) incoming,
    max(dates) outgoing,
    datediff(second, min(dates), max(dates)) / 60.0 / 60 / 24 days_in_station
from (
    select
        t.*,
        sum(case when type = 'Incoming' then 1 else 0 end)
            over(partition by itemID order by dates) grp
    from mytable t
) t
group by itemID, grp

您的问题没有说明当传入/传出记录没有正确交错给定项目时应该发生什么。以下是查询将如何处理它:

  • 如果有两个连续的传入记录,这会在结果集中生成一行,其中传入和传出日期相同,并且在车站的天数是0

  • 如果有两个或多个连续的传出记录,则只考虑最后一个

如果提供有关要求的更多详细信息,则可以对这些进行微调。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-20
    • 2020-10-22
    • 2012-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多