【问题标题】:DB2/Sql grouping with condition带条件的 DB2/Sql 分组
【发布时间】:2022-12-12 10:03:13
【问题描述】:

我有一个非常简单的 sql 查询,我在 DB2 I 系列 4 上运行,它只是执行一些简单的连接。问题是我的材料表有它,因此可以在每个作品上使用多种材料/颜色组合。现在我正在获取每个组合的行,但我想合并以便如果 test.materials.sequence 的值为 2 那么它会创建两个额外的列(如果组合没有序列 2 那么它只是 0 和0 在这些列中。

查询:

Select bod.code, mat.material, mat.mat_color, 
from test.skus sk
inner join test.Bodies bod on sk.body_id = bod.id
inner join test.categories prc on prc.id = sk.category_id
inner join test.skus_to_materials stm on sk.id = stm.sku_id
inner join test.materials mat on stm.mat_id = mat.id
order by prc.desc;

表:

存货单位


id  |  code  |  body_id  |  category_id  
------------------------------------------- 
1      12345     9912            3
2.     12346     9913            3

身体


id   |  code 
--------------------------
9912    1234-5
9913    1234-6

类别


id  |  category
------------------
3     Test

skus_to_materials


id  |  sku_id  |  mat_id  |  sequence
--------------------------------------
1     1           221         1
2     1           222         2
3     2           223         1

材料


id  |  material  |  mat_color 
-------------------------------
221    Fabric       black     
222    Fabric       white     
223    Leather      brown     

这是我目前的结果:

code  | material  | mat_color
-------------------------
1234-5 | Fabric    | black
1234-5 | Fabric    | white

这是我想要的结果:

code | material1 | mat_color1 | material2 | mat_color2
----------------------------------------------------------
1234-5    Fabric        black      Fabric     white
1234-6    Leather       brown       0           0

查看 1234-6 如何只有一种材料组合,因此 material2 和 mat_color2 将为零。

有没有办法通过分组和行操作来实现这一点?

更新:

在回答查尔斯的回答时,我在一个案例中发现了一些数据更多的问题。按材料、颜色和描述分组后,我意识到我得到了丢失的记录,但现在遇到了这个问题:

code   |   material1   |   color1   |  material2  |  color2
------------------------------------------------------------
1234-5      Fabric         White         0               0
1234-5      0               0          Leather         white 
1234-5      Leather         Brown        0               0
1234-5      Leather         Tan          0               0
1234-6      Fabric         Black         0               0 
1234-6      0              0           Leather         Black 
1234-7     Fabric         White          0               0

【问题讨论】:

  • 这将从 dbfiddle 中获益匪浅
  • 我认为 dbfiddle 不支持这种方言。
  • 我有一个去这里 db-fiddle.com/f/u4zKAdw3H4hFLbfnzEeZS2/1@jmarkmurphy 它不支持 DB2 但当前查询适用于 db2 和 mysql

标签: sql db2 db2-400


【解决方案1】:

“行到列”被称为“旋转”数据。

Db2 for IBM i 没有内置的方法来转换。但是,假设有一组不同的值,您可以对其进行硬编码。

像这样的事情应该做你想做的:

Select bod.code, max(mat1.material), max(mat1.mat_color),
       max(mat2.material), max(mat2.mat_color) 
from test.skus sk
inner join test.Bodies bod on sk.body_id = bod.id
inner join test.categories prc on prc.id = sk.category_id
inner join test.skus_to_materials stm on sk.id = stm.sku_id
inner join test.materials mat1 on stm.mat_id = mat1.id
           and mat1.sequence = 1
left outer join test.materials mat2 on stm.mat_id = mat2.id
           and mat2.sequence = 2
group by bod.code
order by prc.desc;

编辑好的,如果序列实际上在 skus_to_materials 中,那么您将需要一组不同的连接。实际上,在那种情况下,我可能只会使用基于 CTE 的语句。

with allrows as (
  Select bod.code, prc.desc, stm.sequence
         , mat.material, mat.mat_color, 
    from test.skus sk
     inner join test.Bodies bod on sk.body_id = bod.id
     inner join test.categories prc on prc.id = sk.category_id
     inner join test.skus_to_materials stm on sk.id = stm.sku_id
     inner join test.materials mat on stm.mat_id = mat.id
}
select 
  code
  , max(case when sequence = 1 then material else '0' end) as material1
  , max(case when sequence = 1 then color else '0' end) as color1
  , max(case when sequence = 2 then material else '0' end) as material2
  , max(case when sequence = 2 then color else '0' end) as color2
from allRows
group by code
order by desc;

【讨论】:

  • 谢谢你的回答,但我在运行它时意识到:我犯了一个大错误,把序列放在材料表上,但它实际上在 skus_to_materials 表中,所以当我修改它以运行时,最后两列的值为空值.我在上面更新了我的数据
  • 您可以将 null 替换为 COALESCE(mat2.color, '0')
  • 我认为我的问题在于连接,因为我只在最后两列中得到空值,即使在某些情况下我应该在所有 4 列中获取值。所以在我上面的例子中,我会得到第一个结果,但目前我没有得到它,因为我把序列放在了错误的表中。
  • @Geoff_S 见编辑
  • 谢谢,这让我更接近了,但在获得更多数据后,我意识到我丢失了记录的问题,我通过将 GROUP BY 更改为按代码、材料、颜色、描述分组来纠正这个问题。但是,现在我得到的结果就像我上面的更新一样。在那个例子中,我现在看到我需要按身体代码的颜色分组,所以在我上面的例子中我应该只结束 5 行。对于代码 1234-6,有 2 行,但它们具有相同的颜色,因此它们需要像 1234-6 | fabric | black | leather | black 一样是一行。我接受了你的回答,只是好奇你是否有任何见解
【解决方案2】:

我认为查尔斯的第一个答案更接近。这是我得到的。

SELECT sk.id SKU
      ,BOD.CODE 
      ,MAT.MATERIAL
      ,MAT.MAT_COLOR
      ,COALESCE(stm2.SEQUENCE, 0)
      ,COALESCE(mat2.material, '0')
      ,COALESCE(mat2.mat_color, '0')
FROM SKUS SK
 INNER JOIN BODIES BOD ON SK.BODY_ID = BOD.ID
 INNER JOIN CATEGORIES PRC ON PRC.ID = SK.CATEGORY_ID
 INNER JOIN SKUS_TO_MATERIALS STM ON SK.ID = STM.SKU_ID AND stm.SEQUENCE = 1
 INNER JOIN MATERIALS MAT ON STM.MAT_ID = MAT.ID
 LEFT JOIN SKUS_TO_MATERIALS STM2 ON SK.ID = STM2.SKU_ID AND stm2.SEQUENCE = 2
 LEFT JOIN MATERIALS MAT2 ON STM2.MAT_ID = MAT2.ID

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    • 2020-07-05
    • 2021-03-27
    • 1970-01-01
    • 1970-01-01
    • 2015-09-10
    相关资源
    最近更新 更多