sql-server - SQL 分区通过交替的行组

标签 sql-server sql-server-2008 tsql data-partitioning

我有一个看起来像这样的数据表。

|Key|LotId|TransactionType|Quantity|Destination
|1  |A    |Transform      |NULL    |Foo
|2  |A    |Transform      |NULL    |Bar
|3  |A    |Consume        |100     |NULL
|4  |B    |Transform      |NULL    |Bob
|5  |B    |Transform      |NULL    |Fred
|6  |B    |Consume        |75      |NULL
|7  |B    |Consume        |50      |NULL
|8  |B    |Transform      |NULL    |Sally
|9  |B    |Transform      |NULL    |Fred
|10 |B    |Consume        |60      |NULL
|11 |C    |Transform      |NULL    |Bar
|12 |C    |Transform      |NULL    |Fred
|13 |C    |Consume        |25      |NULL

转换线告诉我我的数量去了哪里,消耗线告诉我使用了多少数量。消费行适用于该 LotId 的所有先前转换行,直到前一个 LotId 或如果它与前一个转换和消费分组相同的 LotId。并且增加一个 Spanner ,一组内的变换和消耗线的数量是可变的。我确实为我工作的一件事是变换线先出现,然后消耗,下次我遇到变换时,我知道新的分组已经开始。
|Key|LotId|TransactionType|Quantity|Destination|Grouping
|1  |A    |Transform      |NULL    |Foo        |A1
|2  |A    |Transform      |NULL    |Bar        |A1
|3  |A    |Consume        |100     |NULL       |A1
---------------------------------------------------------
|4  |B    |Transform      |NULL    |Bob        |B1
|5  |B    |Transform      |NULL    |Fred       |B1
|6  |B    |Consume        |75      |NULL       |B1
|7  |B    |Consume        |50      |NULL       |B1
---------------------------------------------------------
|8  |B    |Transform      |NULL    |Sally      |B2
|9  |B    |Transform      |NULL    |Fred       |B2
|10 |B    |Consume        |60      |NULL       |B2
---------------------------------------------------------
|11 |C    |Transform      |NULL    |Bar        |C1
|12 |C    |Transform      |NULL    |Fred       |C1
|13 |C    |Consume        |25      |NULL       |C1

(出于本示例的目的,我们将假设数量在所有各方之间平均分配)
  • A1 组有 100 人在 Foo 和 Bar 之间 split
  • B1组Bob和Fred之间有125人 split
  • B2组Sally和Fred之间有60人 split
  • C1组Bar和Fred有25人分

  • 使用 sql RANK() , DENSE_RANK() , & ROW_NUMBER()窗口 我正在尝试解决一个查询,它将给我这个分组。一旦我能够得到这个分组,我就应该能够将数据连接回自身并最终确定我的每个目的地收到了多少。

    这是在 SQL2008 上。

    最佳答案

    使用 common table expression 的组合, outer apply() , 和 dense_rank()

    注意:我更改了列KeytKey所以我不必在它周围使用方括号。

    ;with cte as (
      select *
        , PrevTransactionType=isnull(x.Prev_TransactionType,'Consume')
      from t
      outer apply (
          select top 1
            Prev_TransactionType = TransactionType
          from t as i
          where i.tKey < t.tKey
          order by i.tKey desc 
          ) as x
    )
    select  t.tKey, t.LotId, t.TransactionType, t.Quantity, t.Destination
     , Grouping = LotId + convert(varchar(10),dense_rank() over (
        partition by LotId 
        order by GroupNumber
        )
      )
    from cte as t
    outer apply (
      select top 1 
        GroupNumber = i.tKey
        from cte as i
        where i.tKey <= t.tKey
          and i.TransactionType = 'Transform'
          and i.PrevTransactionType = 'Consume'
        order by i.tKey desc
        ) x
    

    测试设置:http://rextester.com/LWV40248

    结果:
    +------+-------+-----------------+----------+-------------+----------+
    | tKey | LotId | TransactionType | Quantity | Destination | Grouping |
    +------+-------+-----------------+----------+-------------+----------+
    |    1 | A     | Transform       | NULL     | Foo         | A1       |
    |    2 | A     | Transform       | NULL     | Bar         | A1       |
    |    3 | A     | Consume         | 100      | NULL        | A1       |
    |    4 | B     | Transform       | NULL     | Bob         | B1       |
    |    5 | B     | Transform       | NULL     | Fred        | B1       |
    |    6 | B     | Consume         | 75       | NULL        | B1       |
    |    7 | B     | Consume         | 50       | NULL        | B1       |
    |    8 | B     | Transform       | NULL     | Sally       | B2       |
    |    9 | B     | Transform       | NULL     | Fred        | B2       |
    |   10 | B     | Consume         | 60       | NULL        | B2       |
    |   11 | C     | Transform       | NULL     | Bar         | C1       |
    |   12 | C     | Transform       | NULL     | Fred        | C1       |
    |   13 | C     | Consume         | 25       | NULL        | C1       |
    +------+-------+-----------------+----------+-------------+----------+
    

    关于sql-server - SQL 分区通过交替的行组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42426353/

    相关文章:

    c# - 为什么 SqlDataReader to DataTable 只有在我使用单独的字段时才有效?

    来自常量字符串列表的带有 INNER JOIN 的 SQL INSERT

    c# - TSQL BULK INSERT 行错误导致 C# 异常

    tsql - 在查询查询中使用 CFQUERYPARAM 是否有任何合乎逻辑的理由?

    sql-server - 分析服务连接被远程主机关闭(Azure SQL 数据库)

    sql - MSSQL - 选择在两列中找到的不同产品

    c# - 哪种算法更适合加密和解密项目内的数据?

    sql-server-2008 - SQL 选择行样本

    sql - TSQL,确保@符号前至少出现一个字符

    sql-server - ALTER TABLE ALTER COLUMN 会中断正在进行的数据库访问吗?