【问题标题】:MS Access / T-SQL - Grouping Interval DataMS Access / T-SQL - 分组间隔数据
【发布时间】:2018-10-30 01:57:50
【问题描述】:

我在 csv 文件中有一些记录,这些记录通过 MS Access 数据库加载到 MS SQL Server 2016 表中。在将这些记录插入 SQL 数据库表之前,我想使用 VBA 查询或 T-SQL 查询(而不是使用记录集的 VBA 代码)对这些记录进行分组。

示例输入:

ShiftID    Name_ID          From    To  Length  Size    Chargeable**
----------------------------------------------------------------------------
DAY1       CLASSIC_1        0.0     2.8  2.8    NQ2     Yes
DAY1       CLASSIC_1        2.8     5.8  3      NQ2     No
DAY1       CLASSIC_1        5.8     8.0  2.2    NQ2     No
DAY1       CLASSIC_1        8.0     11.1 3.1    NQ2     Yes
DAY1       CLASSIC_1        11.1    14.3 3.2    NQ2     Yes

所需输出:

ShiftID    Name_ID          From    To  Length  Size    Chargeable
----------------------------------------------------------------------
DAY1       CLASSIC_1        0.0     2.8  2.8     NQ2    Yes
DAY1       CLASSIC_1        2.8     8.0  5.2     NQ2    No
DAY1       CLASSIC_1        8.0    14.3  6.3     NQ2    Yes

使用查询:

SELECT ShiftID, Name_ID, Min([From]) AS [From], Max([To]) AS [To], Sum(Length) AS Length, 
Size, Chargeable FROM table1
 GROUP BY ShiftID, Name_ID, Size, Chargeable
 ORDER BY ShiftID, Name_ID, Min([From]), Max([To]), Size, Chargeable;

返回以下记录:

ShiftID Name_ID     From    To   Length  Size   Chargeable
----------------------------------------------------------------
DAY1    CLASSIC_1   0.0     14.3  9.1    NQ2    Yes
DAY1    CLASSIC_1   2.8     8.0   5.2    NQ2    No

这是我所期望的,但不是我需要的。在这种情况下,分组并没有给我正确的 To 深度。正确的查询不应返回重叠的间隔。

【问题讨论】:

  • 只使用直接的 SQL,我脑子里什么都没有。我只能看到在 SQL Server 的存储过程中使用游标,或在 Access 中使用 VBA 通过遍历结果来创建临时表。也许其他人会看到不涉及循环的更明显的解决方案。

标签: sql-server tsql ms-access vba


【解决方案1】:

这是一个差距和孤岛问题。使用以下 T-SQL 查询:

SELECT ShiftID, Name_ID, [From], [To], Length, Size, Chargeable,
       ROW_NUMBER() OVER (PARTITION BY ShiftID, Name_ID, Size 
                          ORDER BY [From]) - 
       ROW_NUMBER() OVER (PARTITION BY ShiftID, Name_ID, Size, Chargeable
                          ORDER BY [From]) AS grp
FROM Table1

产生以下输出:

ShiftID Name_ID     From  To    Length  Size    Chargeable  grp
---------------------------------------------------------------
DAY1    CLASSIC_1   3     5     3       NQ2     No          1
DAY1    CLASSIC_1   6     8     2       NQ2     No          1
DAY1    CLASSIC_1   0     2     3       NQ2     Yes         0
DAY1    CLASSIC_1   8     11    3       NQ2     Yes         2
DAY1    CLASSIC_1   11    14    3       NQ2     Yes         2

您现在可以使用grp 来合并记录:

SELECT ShiftID, Name_ID, Size, 
       MIN([From]) AS [From], MAX([To]) AS [To], SUM(Length) AS Length,
       Chargeable
FROM (
    SELECT ShiftID, Name_ID, [From], [To], Length, Size, Chargeable,
           ROW_NUMBER() OVER (PARTITION BY ShiftID, Name_ID, Size 
                              ORDER BY [From]) - 
           ROW_NUMBER() OVER (PARTITION BY ShiftID, Name_ID, Size, Chargeable 
                              ORDER BY [From]) AS grp
    FROM Table1) AS t
GROUP BY ShiftID, Name_ID, Size, Chargeable, grp

Demo here

【讨论】:

  • 这对我有用。感谢 Giorgos 发布此内容并让我知道正确的术语 - 间隙和岛屿。
  • @Kanga5 很高兴我能够提供帮助并欢迎来到 Stack Overflow。如果它帮助您解决问题,请将此或任何其他答案标记为已接受。
【解决方案2】:

Access SQL中可以用子查询来完成:

SELECT 
    MeasureLevel.ShiftID,
    MeasureLevel.Name_ID,
    Min(MeasureLevel.From) AS [From], 
    Max(MeasureLevel.To) AS [To], 
    Sum(MeasureLevel.Length) AS Length, 
    MeasureLevel.Size,
    MeasureLevel.Chargeable
FROM
    (SELECT 
        Measure.ShiftID,
        Measure.Name_ID,
        Measure.From, 
        Measure.To, 
        Measure.Length, 
        Measure.Size,
        Measure.Chargeable, 
        (Select 
            Max(T.From) 
        From 
            Measure As T 
        Where 
            T.From <= Measure.To And 
            T.Chargeable = Measure.Chargeable) AS [Level]
    FROM 
        Measure) As MeasureLevel
GROUP BY 
    MeasureLevel.ShiftID,
    MeasureLevel.Name_ID,
    MeasureLevel.Level, 
    MeasureLevel.Size,
    MeasureLevel.Chargeable

【讨论】:

  • 您好 Gustav,看起来此 Access SQL 查询在 Chargeable 字段发生更改的情况下有效。但是,如果每条记录的 Chargeable 字段都相同,则不会对记录进行分组(每条记录的 Level 字段都不同)。但我得到了使用子查询的想法,所以谢谢你看这个。
猜你喜欢
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 2018-04-20
  • 1970-01-01
  • 2021-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多