Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

bergabung dengan kolom data yang dibatasi koma

Idealnya, solusi terbaik Anda adalah menormalkan Tabel2 sehingga Anda tidak menyimpan daftar yang dipisahkan koma.

Setelah data ini dinormalisasi, Anda dapat dengan mudah melakukan kueri data. Struktur tabel baru mungkin mirip dengan ini:

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')
;

Menormalkan tabel akan memudahkan Anda untuk melakukan kueri data dengan menggabungkan tabel:

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

Lihat Demo

Kemudian jika Anda ingin menampilkan data sebagai daftar yang dipisahkan koma, Anda dapat menggunakan FOR XML PATH dan STUFF :

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;

Lihat Demo.

Jika Anda tidak dapat menormalkan data, maka ada beberapa hal yang dapat Anda lakukan.

Pertama, Anda dapat membuat fungsi split yang akan mengubah data yang disimpan dalam daftar menjadi baris yang dapat digabungkan. Fungsi split akan mirip dengan ini:

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;

Saat Anda menggunakan fungsi split, Anda dapat membiarkan data dalam beberapa baris atau Anda dapat menggabungkan nilai kembali ke dalam daftar yang dipisahkan koma:

;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

Lihat Demo.

Cara terakhir agar Anda bisa mendapatkan hasilnya adalah dengan menerapkan FOR XML PATH secara langsung.

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;

Lihat SQL Fiddle dengan 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. Bagaimana cara mengatur variabel dari kueri SQL?

  2. Dapatkan semua orang tua untuk seorang anak

  3. Fungsi vs Prosedur Tersimpan

  4. Konversi 'datetime' menjadi 'smalldatetime' di SQL Server (Contoh T-SQL)

  5. Kembalikan Tipe Data Dasar dari Nilai Varian SQL di SQL Server