如何使用Case语句在一列中创建多行



我需要将多行连接到一列中。我有一张这样的桌子。

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值替换为0s
  • 使用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

相关内容

  • 没有找到相关文章

最新更新