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

Chức năng tách trong SQL Server 2008

Đầu tiên, giải pháp tốt nhất của bạn là không lưu trữ dữ liệu trong danh sách được phân tách bằng dấu phẩy trong cơ sở dữ liệu của bạn. Bạn nên xem xét việc sửa cấu trúc bảng.

Nếu bạn không thể thay đổi cấu trúc bảng, thì bạn sẽ cần phải chia dữ liệu trong danh sách thành các hàng để gán tên chính xác. Sau khi dữ liệu được chia nhỏ, bạn có thể nối dữ liệu trở lại danh sách.

Có nhiều split khác nhau mà bạn có thể tìm thấy trực tuyến nhưng đây là phiên bản mà tôi thường sử dụng:

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;

Để có được kết quả của bạn, tôi sẽ bắt đầu bằng cách áp dụng split và một row_number() vì tôi không thấy một khóa duy nhất được liên kết với mỗi hàng. Nếu bạn có một khóa duy nhất trên mỗi hàng thì bạn sẽ không cần row_number() :

;with cte as
(
  select rn, name, id
  from
  (
    select row_number() over(order by (select 1)) rn,
      databasename
    from table2
  ) t2
  cross apply dbo.split(t2.databasename, ',') i
  inner join table1 t1
    on i.items = t1.id
) 
select *
from cte

Truy vấn này chia danh sách được phân tách bằng dấu phẩy của bạn thành như sau:

| RN |   NAME | ID |
--------------------
|  1 |  MSSQL |  1 |
|  1 | Oracle |  3 |
|  2 |  MySQl |  2 |
|  3 |  MSSQL |  1 |
|  3 |  MySQl |  2 |

Khi bạn có dữ liệu trong nhiều hàng với name chính xác , sau đó bạn có thể sử dụng STUFF()FOR XML PATH để nối nó vào danh sách. Truy vấn đầy đủ của bạn sẽ tương tự như sau:

;with cte as
(
  select rn, name, id
  from
  (
    select row_number() over(order by (select 1)) rn,
      databasename
    from table2
  ) t2
  cross apply dbo.split(t2.databasename, ',') i
  inner join table1 t1
    on i.items = t1.id
) 
select  
  STUFF(
         (SELECT ', ' + c2.name
          FROM cte c2
          where c1.rn = c2.rn
          order by c2.id
          FOR XML PATH (''))
          , 1, 1, '') Databasename
from cte c1
group by c1.rn
order by c1.rn;

Xem SQL Fiddle với Demo.

Kết quả của truy vấn đầy đủ là:

|   DATABASENAME |
------------------
|  MSSQL, Oracle |
|          MySQl |
|   MSSQL, MySQl |


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách nối các chuỗi trong SQL Server với CONCAT ()

  2. Tạo một bảng SQL Server từ một dữ liệu C #

  3. Tự động chống phân mảnh chỉ mục trong cơ sở dữ liệu MS SQL Server

  4. CẬP NHẬT nếu tồn tại CHÈN khác trong SQL Server 2008

  5. Chuyển đổi tên tháng thành số tháng trong SQL Server (T-SQL)