Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

nối cột dữ liệu được phân tách bằng dấu phẩy

Lý tưởng nhất, giải pháp tốt nhất của bạn là chuẩn hóa Table2 để bạn không lưu trữ danh sách được phân tách bằng dấu phẩy.

Khi bạn đã chuẩn hóa dữ liệu này thì bạn có thể dễ dàng truy vấn dữ liệu. Cấu trúc bảng mới có thể tương tự như sau:

CREATE TABLE T1
(
  [col1] varchar(2), 
  [col2] varchar(5),
  constraint pk1_t1 primary key (col1)
);

INSERT INTO T1
    ([col1], [col2])
VALUES
    ('C1', 'john'),
    ('C2', 'alex'),
    ('C3', 'piers'),
    ('C4', 'sara')
;

CREATE TABLE T2
(
  [col1] varchar(2), 
  [col2] varchar(2),
  constraint pk1_t2 primary key (col1, col2),
  constraint fk1_col2 foreign key (col2) references t1 (col1)
);

INSERT INTO T2
    ([col1], [col2])
VALUES
    ('R1', 'C1'),
    ('R1', 'C2'),
    ('R1', 'C4'),
    ('R2', 'C3'),
    ('R2', 'C4'),
    ('R3', 'C1'),
    ('R3', 'C4')
;

Việc chuẩn hóa các bảng sẽ giúp bạn truy vấn dữ liệu dễ dàng hơn nhiều bằng cách nối các bảng:

select t2.col1, t1.col2
from t2
inner join t1
  on t2.col2 = t1.col1

Xem Demo

Sau đó, nếu bạn muốn hiển thị dữ liệu dưới dạng danh sách được phân tách bằng dấu phẩy, bạn có thể sử dụng FOR XML PATHSTUFF :

select distinct t2.col1, 
  STUFF(
         (SELECT distinct ', ' + t1.col2
          FROM t1
          inner join t2 t
            on t1.col1 = t.col2
          where t2.col1 = t.col1
          FOR XML PATH ('')), 1, 1, '') col2
from t2;

Xem Demo.

Nếu bạn không thể chuẩn hóa dữ liệu, thì có một số điều bạn có thể làm.

Đầu tiên, bạn có thể tạo một hàm tách sẽ chuyển đổi dữ liệu được lưu trữ trong danh sách thành các hàng có thể được nối với nhau. Hàm tách sẽ tương tự như sau:

CREATE FUNCTION [dbo].[Split](@String varchar(MAX), @Delimiter char(1))       
returns @temptable TABLE (items varchar(MAX))       
as       
begin      
    declare @idx int       
    declare @slice varchar(8000)       

    select @idx = 1       
        if len(@String)<1 or @String is null  return       

    while @idx!= 0       
    begin       
        set @idx = charindex(@Delimiter,@String)       
        if @idx!=0       
            set @slice = left(@String,@idx - 1)       
        else       
            set @slice = @String       

        if(len(@slice)>0)  
            insert into @temptable(Items) values(@slice)       

        set @String = right(@String,len(@String) - @idx)       
        if len(@String) = 0 break       
    end   
return 
end;

Khi bạn sử dụng hàm tách, bạn có thể để dữ liệu trong nhiều hàng hoặc bạn có thể nối các giá trị lại thành một danh sách được phân tách bằng dấu phẩy:

;with cte as
(
  select c.col1, t1.col2
  from t1
  inner join 
  (
    select t2.col1, i.items col2
    from t2
    cross apply dbo.split(t2.col2, ',') i
  ) c
    on t1.col1 = c.col2
) 
select distinct c.col1, 
  STUFF(
         (SELECT distinct ', ' + c1.col2
          FROM cte c1
          where c.col1 = c1.col1
          FOR XML PATH ('')), 1, 1, '') col2
from cte c

Xem Demo.

Cách cuối cùng mà bạn có thể nhận được kết quả là áp dụng FOR XML PATH trực tiếp.

select col1, 
(
  select ', '+t1.col2
  from t1
  where ','+t2.col2+',' like '%,'+cast(t1.col1 as varchar(10))+',%'
  for xml path(''), type
).value('substring(text()[1], 3)', 'varchar(max)') as col2
from t2;

Xem SQL Fiddle với Demo



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sử dụng merge..output để ánh xạ giữa source.id và target.id

  2. cách cấu hình tệp cấu hình ngủ đông cho máy chủ sql

  3. SQLException:Dữ liệu chuỗi hoặc nhị phân sẽ bị cắt bớt

  4. Làm cách nào để thêm chuỗi có giá trị tăng tự động trong SQL Server?

  5. Xóa số khỏi máy chủ sql chuỗi