我需要将多行连接到一列中。我有一张这样的桌子。
PRD_ID PRD_CONTAINER CONTAINER_LVL QTY
---------- --------------------- -------------
122 BIG_BOX 4
122 MED_BOX 3 6
122 SML_BOX 2
122 NO_BOX 1 50
所有数量值都应该在一列下,从级别4到1开始。如果没有"数量"的值,则应将其标记为0/。我想要的结果就像这个
PRD_ID QTY
---------- -------
122 0/6/0/50
我试过这个
SELECT
PRD_ID,
(CASE WHEN CONTAINER_LVL = 4 AND QTY > 0 THEN dbo.FBE_GetThousandSeparator(QTY,0) ELSE '0/' END +
CASE WHEN CONTAINER_LVL = 3 AND QTY > 0 THEN dbo.FBE_GetThousandSeparator(QTY,0) ELSE '0/' END +
CASE WHEN CONTAINER_LVL = 2 AND QTY > 0 THEN dbo.FBE_GetThousandSeparator(QTY,0) ELSE '0/' END +
CASE WHEN CONTAINER_LVL = 1 AND QTY > 0 THEN dbo.FBE_GetThousandSeparator(QTY,0) ELSE '' END) AS
QTY
FROM
#TMP2
GROUP BY
PRD_ID,
(CASE WHEN CONTAINER_LVL = 4 AND QTY > 0 THEN dbo.FBE_GetThousandSeparator(QTY,0) ELSE '0/' END +
CASE WHEN CONTAINER_LVL = 3 AND QTY > 0 THEN dbo.FBE_GetThousandSeparator(QTY,0) ELSE '0/' END +
CASE WHEN CONTAINER_LVL = 2 AND QTY > 0 THEN dbo.FBE_GetThousandSeparator(QTY,0) ELSE '0/' END +
CASE WHEN CONTAINER_LVL = 1 AND QTY > 0 THEN dbo.FBE_GetThousandSeparator(QTY,0) ELSE '' END)
我的结果是:
PRD_ID QTY
---------- -------
122 0/0/0/
122 0/0/0/50
122 0/60/
根据@Larnu的注释,可以使用字符串聚合。此外,如果您只是检查null(而不是负),则不需要case
表达式。
select PRD_ID,
string_agg(
convert(nvarchar(32), coalesce(QTY,0))
, '/'
) within group (order by CONTAINER_LVL desc) as QTY
from #TMP
group by PRD_ID
在上面我们:
- 使用
coalesce
将任何null
值替换为0
s - 使用
convert
将整数更改为字符串 - 使用
string_agg
将所有字符串连接在一起,并使用/
作为分隔符 - 使用
within group (order by CONTAINER_LVL desc)
确定字段返回的顺序(即CONTAINER_LVL的QTY先为4,然后为3,等等)
相关文档:https://learn.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-ver16#f-generate-a-storted-list-of-emails-per-towns
如果这不是一个选项(即string_agg
仅在SQL 2017中引入):
select PRD_ID,
convert(nvarchar(32), coalesce(max(case when CONTAINER_LVL = 4 then QTY end),0))
+ N'/' +
convert(nvarchar(32), coalesce(max(case when CONTAINER_LVL = 3 then QTY end),0))
+ N'/' +
convert(nvarchar(32), coalesce(max(case when CONTAINER_LVL = 2 then QTY end),0))
+ N'/' +
convert(nvarchar(32), coalesce(max(case when CONTAINER_LVL = 1 then QTY end),0))
from #TMP
group by PRD_ID
在上面我们:
- 使用CASE表达式获取给定位置的给定CONTAINER_LVL值的QTY值;对于所有没有CONTAINER_LVL的行,我们在这里得到NULL。如果该CONTAINER_LVL的QTY值为NULL,我们也会得到NULL
- 将其封装在CCD_ 10中,使得组内的多个行的值(包括NULLS)为"0";压扁的"/聚合为单个值;在这种情况下,最大值。如果所有行都有NULL,那将是NULL,如果我们有一个数值,其余为NULL(正如通常预期的那样),我们将得到该数值;如果我们有多个数值(即,因为我们有两行具有相同的PRD_ID和CONTAINER_LVL值),我们会得到具有最高QTY值的一个。。。尽管我假设最后一种情况不是有效的,并且你有一个唯一的约束来防止它。注意:如果你愿意,你也可以在这里使用
SUM
;那么,如果有多行具有相同的PRD_ID和CONTAINER_LVL值,则它们的QTY将组合用于该位置的值 - 我们将其封装在
coalesce
函数中,这样,如果值为NULL,我们将其替换为0 - 我们将其封装在
convert
函数中,这样我们就可以对该值执行字符串串联(即'0' + '/'
有效…0 + '/'
无效) - 然后我们在这些值中的每一个之间使用CCD_ 16来按预期连接4个值
SQL Fiddle演示
也许使用PIVOT可以解决您的问题,试试这个;
SELECT PROD_ID, [1] AS NO, [2] AS SML, [3] AS MED, [4] AS BIG
FROM #TMP2
PIVOT (
SUM(QTY)
FOR CONTAINER_LVL IN ([1], [2], [3], [4])
) P