sql >> データベース >  >> RDS >> Sqlserver

SQLServer2008の分割機能

    まず、最善の解決策は、データベースのコンマ区切りのリストにデータを保存しないことです。テーブル構造の修正を検討する必要があります。

    テーブル構造を変更できない場合は、リスト内のデータを行に分割して、正しい名前を割り当てる必要があります。データが分割されたら、データを連結してリストに戻すことができます。

    多くの異なるsplitがあります オンラインで見つけることができる機能ですが、これが私が通常使用するバージョンです:

    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;
    

    結果を得るには、まずsplitを適用します 関数とrow_number() 各行に関連付けられた一意のキーが表示されないためです。各行に一意のキーがある場合は、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
    

    このクエリは、カンマ区切りのリストを次のように分割します。

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

    正しいnameで複数の行にデータを配置したら 、次にSTUFF()を使用できます およびFOR XML PATH それをリストに連結します。完全なクエリは次のようになります:

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

    SQL FiddlewithDemoを参照してください。

    完全なクエリの結果は次のとおりです。

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


    1. ProxySQL:すべてのSevereninesリソース

    2. SQLステートメントですべてのパラメーターが使用されたわけではありません(Python、MySQL)

    3. 遅いクエリでMySQLのパフォーマンスの問題を特定する方法

    4. SQL Server AlwaysOn可用性グループ:インストールと構成。パート2