简体   繁体   English

SQL中如何将单行数据拆分成多行?

[英]How to split the data in a single row into multiple rows in SQL?

I have a table in the following format我有以下格式的表格

ProjectID           LocationID
1                   [1,2,3,4]
2                   [2,3]

Can I split the data in the column LocationID into multiple rows like below?我可以将 LocationID 列中的数据拆分为如下所示的多行吗?

ProjectID           LocationID
1                   1
1                   2
1                   3
1                   4
2                   2
2                   3

I need to get the data loaded to Power-Bi using the SQL only.我只需要使用 SQL 将数据加载到 Power-Bi。 is it possible?可能吗?

If data type of locationID is varchar then:如果 locationID 的数据类型是 varchar 则:

 create table projects (ProjectID int, LocationID varchar(50));
 insert into projects values(1,                  '[1,2,3,4]');
 insert into projects values(2,                  '[2,3]');

Query:询问:

select projectid, value 
 from projects 
 CROSS APPLY STRING_SPLIT(replace(replace(locationid,'[',''),']',''),',')

Output: Output:

projectid投影 value价值
1 1 1 1
1 1 2 2
1 1 3 3
1 1 4 4
2 2 2 2
2 2 3 3

db<fiddle here db<小提琴在这里

Solution for SQL Server 2014 SQL 服务器解决方案 2014

 create table projects (ProjectID int, LocationID nvarchar(max));
 insert into projects values(1,                  '[1,2,3,4]');
 insert into projects values(2,                  '[2,3]');

Query:询问:

     WITH tmp AS
(
    SELECT
        ProjectID,
        LEFT(replace(replace(locationid,'[',''),']',''), CHARINDEX(',', replace(replace(locationid,'[',''),']','') + ',') - 1) LocationID,
        STUFF(replace(replace(locationid,'[',''),']',''), 1, CHARINDEX(',', replace(replace(locationid,'[',''),']','') + ','), '') b
    FROM projects
    
    UNION all

    SELECT
        ProjectID,
        LEFT(b, CHARINDEX(',', b + ',') - 1),
        STUFF(b, 1, CHARINDEX(',', b + ','), '')
    FROM tmp
    WHERE
        b > ''
)

SELECT
    ProjectID, LocationID
FROM tmp
ORDER BY projectid
 

Output: Output:

ProjectID项目 ID LocationID位置 ID
1 1 1 1
1 1 2 2
1 1 3 3
1 1 4 4
2 2 2 2
2 2 3 3

db<fiddle here db<小提琴在这里

In SQL Server 2014, you can use a recursive CTE -- which Kazi also proposes.在 SQL Server 2014 中,您可以使用递归 CTE——Kazi 也提出了这一点。 I think this is a slightly simpler version:我认为这是一个稍微简单的版本:

with cte as (
      select projectId, convert(varchar(max), null) as locationid,
             convert(varchar(max), substring(LocationId, 2, len(locationId) - 2)) + ',' as rest
      from t
      union all
      select projectId,
             left(rest, charindex(',', rest) - 1),
             stuff(rest, 1, charindex(',', rest), '')
      from cte
      where rest <> ''
     )
select projectid, locationid
from cte
where locationid is not null;

Here is a db<>fiddle. 是一个 db<>fiddle。

In particular, the anchor part just sets up the data -- it does not extract any elements from the string.特别是,锚部分只是设置数据——它不从字符串中提取任何元素。 So, all the logic is in the recursive part, which I find easier to maintain.所以,所有的逻辑都在递归部分,我发现它更容易维护。

I used STRING_SPLIT() which is a table valued function supports SQL server 2016 and higher versions.我使用了 STRING_SPLIT() 这是一个表值 function 支持 SQL 服务器 2016 和更高版本。 You need to provide the formatted string into this function and use cross apply to join and generate the desired output.您需要在此 function 中提供格式化字符串,并使用交叉应用来连接并生成所需的 output。

SELECT
    projectID
   , REPLACE(REPLACE(locationId,'[',''),']','') as [locationid]  
INTO #temp_table
FROM split_string -- Add your table name here


SELECT 
    projectID
    ,VALUE [locationid]  
FROM     #temp_table
CROSS APPLY STRING_SPLIT( [locationid] , ',');

结果

Thanks everyone for helping me out.感谢大家帮助我。 This solution works for my scenario.此解决方案适用于我的场景。

Select projectID,locationid_list from project CROSS APPLY OPENJSON(locationid, '$') WITH (locationid_list int '$') Select projectID,locationid_list from project CROSS APPLY OPENJSON(locationid, '$') WITH (locationid_list int '$')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM