Sql DB2将唯一的列值连接成一行,逗号分隔
两张表:Sql DB2将唯一的列值连接成一行,逗号分隔,sql,ibm-midrange,db2-400,Sql,Ibm Midrange,Db2 400,两张表: Parts Table: Part_Number Load_Date TQTY m-123 19940102 32 1234Cf 20010809 3 wf9-2 20160421 14 Locations Table: PartNo Condition Location QTY m-123 U A02 2 1234Cf S
Parts Table:
Part_Number Load_Date TQTY
m-123 19940102 32
1234Cf 20010809 3
wf9-2 20160421 14
Locations Table:
PartNo Condition Location QTY
m-123 U A02 2
1234Cf S A02 3
m-123 U B01 1
wf9-2 S A06 7
m-123 S A18 29
wf9-2 U F16 7
Result:
Part_Number Load_Date TQTY U_LOC UQTY S_LOC SQTY
m-123 19940102 32 A02,B01 3 A18 29
1234Cf 20010809 3 A02 3
wf9-2 20160421 14 F16 7 A06 7
我很难用当前的DB2版本找到解决方案。我不完全确定如何找到该版本,但它正在AS400系统上运行,而且DB2的版本似乎与OS版本有关。该框正在使用的操作系统:i5/OS版本:V5R4M0
(我使用这些建议尝试了一些命令来获得DB2版本,但没有一个像大多数人所说的那样有效)
关于将多行列数据连接到一行,我遇到了许多文章,其中说明要使用XMLAGG或xmlserialize,但我遇到一个错误,说明该命令无法识别
我不知道从这里可以走到哪里,因为似乎有解决方案,但我无法让那些已经建议的函数工作
编辑: 使用公认的答案和解释,以及示例 通过一个简单的例子来了解递归的基本概念,这是
使用“
selectrownumber()over(partitionbycategory)
”语句,这确实有助于将所有内容整合在一起。当然,一旦我理解了那句话
我还学会了确保递归中使用的数据尽可能缩小,然后在以后与额外的数据合并。这使得结果以指数级的速度增长 不知道UQTY、S_LOC、SQTY的规则是什么,但这是您询问的专栏---
这相当复杂,因此我将展示我所有的工作: 表定义
create table parts
(part_number Varchar(64),
load_date Date,
total_qty Dec(5,0));
create table locations
(part_number Varchar(64),
condition Char(1),
location Char(3),
qty Dec(5,0));
insert into parts
values ('m-123', '1994-01-02', 32),
('1234Cf', '2001-08-09', 3),
('wf9-2', '2016-04-21', 14);
insert into locations
values ('m-123', 'U', 'A02', 2),
('1234Cf', 'S', 'A02', 3),
('m-123', 'U', 'B01', 1),
('wf9-2', 'S', 'A06', 7),
('m-123', 'S', 'A18', 29),
('wf9-2', 'U', 'F16', 7);
查询:
with -- CTE's
-- This collects locations into a comma seperated list
tmp (part_number, condition, location, csv, level) as (
select part_number, condition, min(location),
cast(min(location) as varchar(128)), 1
from locations
group by part_number, condition
union all
select a.part_number, a.condition, b.location,
a.csv || ',' || b.location, a.level + 1
from tmp a
join locations b using (part_number, condition)
where a.csv not like '%' || b.location || '%'
and b.location > a.location),
-- This chooses the correct csv list, and adds quantity for the condition
tmp2 (part_number, condition, csv, qty) as (
select t.part_number, t.condition, t.csv,
(select sum(qty) qty
from locations
where part_number = t.part_number
and condition = t.condition)
from tmp t
where level = (select max(level)
from tmp
where part_number = t.part_number
and condition = t.condition))
-- This is the final select that combines the parts file with
-- the second stage CTE and arranges things horizontally by condition
select p.part_number, p.load_date,
(select sum(qty)
from locations
where part_number = p.part_number) as total_qty,
coalesce(u.csv, '') as u_loc,
coalesce(u.qty, 0) as uqty,
coalesce(s.csv, '') as s_loc,
coalesce(s.qty, 0) as sqty
from parts p
left outer join tmp2 u
on u.part_number = p.part_number and u.condition = 'U'
left outer join tmp2 s
on s.part_number = p.part_number and s.condition = 'S'
order by p.load_date;
编辑我不得不在这里添加一些额外的位,以支持零件/条件的两个以上位置,并且我已经使CTE中的列命名更加一致。好的,让我解释一下,这个问题有3个部分,2个CTE和查询,你可以看到这三个部分被注释分开。第一个CTE是递归CTE。它的目的是生成逗号分隔的位置列表。您应该能够自行运行select来查看它的功能
tmp
是表名,零件号、条件、csv和级别是列名。递归CTE需要一个SELECT
来初始化CTE,需要一个UNION ALL
和一个SELECT
来填充下一个细节。在这种情况下,启动SELECT
检索该组合的零件号、条件和第一个位置(按字母顺序)。级别设置为1。如果仅运行启动选择,您将获得:
part_number condition location csv level
----------- --------- -------- --- -----
1234Cf S A01 A02 1
m-123 S A18 A18 1
m-123 U A02 A02 1
wf9-2 U F16 F16 1
wf9-2 S A06 A06 1
注意每个零件/条件一行。递归CTE的剩余部分将填充csv
中的剩余位置,但它实际上会添加额外的记录,因此我们需要在此处和以后过滤结果。因此,在添加记录时会对其进行处理。上面列出的第一行与位置文件连接
关于零件号和条件。注:在启动选择中,我将第二个min(位置)
转换为varchar(128)
。这为CSV
列留出了扩展空间。如果没有这一点,它仍将扩张,但不足以容纳2个以上的位置
递归CTE中的第二个选择将逗号和下一个位置连接到CSV
的末尾。执行此操作的特定位是a.csv | |','| | b.location
。它还会增加“级别”列。这有助于我们跟踪查询中的位置。最后,具有最高级别的行就是我们要使用的行。我们还有一种结束递归的方法,还有一些过滤器可以减少添加到临时结果集中的行数。如果我们有两个位置,A02
和B02
,如果不选中,我们将得到以下行:A02
,A02,A02
,A02,B02
,A02,B02,A02
,code>A02,A02,B02
,A02,A02
,A02,B02
。。。无限的。反重复筛选器中a.csv与“%”| | b.location | |“%”
不同,对于两个位置,反重复筛选器足以结束递归,并最小化行,如上所述,对于位置A02
和B02
,使用反重复筛选器,我们将获得行A02
,以及A02,B02
。请注意,不会返回第一个示例中具有重复位置的任何其他结果。添加第三个位置C02
将产生以下行(带有防重复过滤器):A02
,A02,B02
,A02,C02
,A02,B02,C02
,A02,C02,B02
。这里没有重复的行,但是我们有多余的行,当您添加位置时,情况会变得更糟。这就是我们需要一种方法来检测这些冗余行的地方。由于我们从最低的位置编号开始,因此我们始终可以确保添加到CSV
的位置大于先前添加的位置。要做到这一点,我们只需在结果集中包含一列,指示添加了哪一列(我们可以询问CSV
,但这更难)。这就是为什么我们需要tmp
中的location
列。然后我们可以编写filterb.location>a.location
。在上面的3个位置示例中,此过滤器防止行A02、C02、B02
只留下一行,包含所有三个位置。将三个以上的位置添加到位置文件将导致TMP
中的行数进一步扩大,但对于每个零件和条件,只有一行包含所有位置,并且将按升序包含所有位置
第二个CTE做两件事。首先,它过滤TMP
,除去包含给定零件/条件的所有位置的行以外的所有行。其次,它累加每个零件/条件的总数量
执行过滤的位位于where
子句中:
where level = (select max(level)
from tmp
where part_number = t.part_number
and condition = t.condition))
非常直截了当。比特
where level = (select max(level)
from tmp
where part_number = t.part_number
and condition = t.condition))
(select sum(qty) qty
from locations
where part_number = t.part_number
and condition = t.condition)
select p.part_number, p.load_date,
(select sum(qty) from locations where part_number = p.part_number) as total_qty,
coalesce(u.csv, '') as u_loc, coalesce(u.qty, 0) as uqty,
coalesce(s.csv, '') as s_loc, coalesce(s.qty, 0) as sqty
from parts p
left outer join tmp2 u
on u.part_number = p.part_number and u.condition = 'U'
left outer join tmp2 s
on s.part_number = p.part_number and s.condition = 'S'
order by p.load_date
part_number load_date tqty u_loc uqty s_loc sqty
----------- ---------- ---- ------- ---- ----- ----
m-123 1994-01-02 32 A02,B01 3 A18 29
1234Cf 2001-08-09 3 0 A02 3
wf9-2 2016-04-21 14 F16 7 A06 7