【问题标题】:将列值拆分为新行
【发布时间】:2022-01-23 11:04:31
【问题描述】:

我有一个这样的 SQL Server 表:

id description items
123 Women clothing T-shirt & Bottom & Top
124 sports items badminton racket
125 gadgets iphone & airpod & charging

我想将items 列的值拆分为每个项目的新行,如下所示:

id description items
123 Women clothing T-shirt
123 Women clothing Bottom
123 Women clothing Top
124 sports items badminton racket
125 gadgets iphone
125 gadgets airpod
125 gadgets charging

【问题讨论】:

  • 根据问题指南,请展示您的尝试并告诉我们您发现了什么(在本网站或其他地方)以及为什么它不能满足您的需求。
  • 提问时,您需要提供minimal reproducible example: (1) DDL 和样本数据填充,即 CREATE 表加上 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上述#1 中的样本数据。 (4) 您的 SQL Server 版本 (SELECT @@version;)。

标签: sql sql-server tsql


【解决方案1】:

要创建函数,请查看此屏幕截图。选择您的数据库并执行以下操作:

如果你没有 string_split 函数。 (低于 sqlserver2016)你可以使用这个功能,它在我们的生产环境中工作多年:

USE xxx
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[StringSplit]
        (@pString VARCHAR(8000), @pDelimiter CHAR(1))
RETURNS TABLE WITH SCHEMABINDING AS
 RETURN

  WITH E1(N) AS (
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
                ),                          
       E2(N) AS (SELECT 1 FROM E1 a, E1 b), 
       E4(N) AS (SELECT 1 FROM E2 a, E2 b), 
 cteTally(N) AS (
                 SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
                ),
cteStart(N1) AS (
                 SELECT 1 UNION ALL
                 SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter
                ),
cteLen(N1,L1) AS(
                 SELECT s.N1,
                        ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000)
                   FROM cteStart s
                )
 SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
        Item       = SUBSTRING(@pString, l.N1, l.L1)
   FROM cteLen l
;

和查询:

select * from 
(SELECT 123 id,      'T-shirt & Bottom & Top' T UNION ALL
 SELECT 124 ,     'badminton racket'UNION ALL
 SELECT 125 , 'iphone & airpod & charging' ) x
CROSS APPLY dbo.StringSplit(x.T, '&')

【讨论】:

  • 对不起,我能知道我应该在哪里创建这个函数吗?我是新手。
  • ok,为你添加截图
  • 再次检查我的答案
  • 你应该了解VALUES构造函数,它比UNION ALL要短得多
  • 感谢您在这方面的帮助。欣赏它。
【解决方案2】:
WITH CTE(id ,description,items) AS
(
 SELECT 123, 'Women clothing' , 'T-shirt & Bottom & Top' UNION ALL
 SELECT 124 ,'sports items' ,'badminton racket'UNION ALL
 SELECT 125 ,'gadgets' ,'iphone & airpod & charging'
)
SELECT C.ID, C.DESCRIPTION, TRIM(S.VALUE)
FROM CTE AS C
CROSS APPLY STRING_SPLIT(C.items, '&') S; 

【讨论】:

  • 伟大的代码@Sergey
  • @NAJAA BAZILAH 不要忘记标记为答案。
  • My SQL Server 没有 STRING_SPLIT 函数。
  • SELECT @@VERSION 的输出是什么
  • @Sergey @@VERSION 它返回 SQL Server 的版本。类似于 Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) Sep 24 2019 13:48:23 版权所有 (C) 2019 Microsoft Corporation Enterprise Edition (64-bit) o​​n Windows 10 Pro 10.0 (Build 19043: ) 你可以用作:SELECT @@VERSION
【解决方案3】:

您可以轻松使用以下 SQL 服务器代码:

select Tbl.RowID,
       Tbl.ColMain,
       [value] ExtractedValue from 
(
SELECT 123 as RowID,      'T-shirt & Bottom & Top' As ColMain UNION ALL
 SELECT 124 ,     'badminton racket' UNION ALL
 SELECT 125 , 'iphone & airpod & charging' 
 ) Tbl
CROSS APPLY String_Split(Tbl.ColMain, '&')

【讨论】:

  • @NAJAA BAZILAH 享受我的妹妹。
猜你喜欢
  • 2019-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-12
  • 1970-01-01
  • 1970-01-01
  • 2019-01-09
  • 2020-02-10
相关资源
最近更新 更多