-1

次のテーブルがあります。

Orders
  id int
  orderName varchar(5000)

Communication
  body varchar(5000)
  attachment varchar(5000)

サンプル注文データ:

id   name
132  ordGD
589  ordPG
6321 ordMF

サンプル通信データ:

body    attachment
body1   132,589,6321

2 つの列 {body,Attachment} を取得するストアド プロシージャを作成したいCommunication

SP では、入力@attachment varchar(5000)には Orders テーブルを参照するカンマ区切りの複数の orderid が含まれます。

問題: @Attachment に一致する Orders からの Orderid に従って OrderName が必要です

4

2 に答える 2

1

このタイプのプロセスでは、列splitにあるデータが必要です。attachmentこれに似たものを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

これはテーブルを返すため、データを結合できます。したがって、クエリは次のようになります。

select o.id,
  o.name,
  c.body
from orders o
left join 
(
  select c.body, s.items as o_id
  from communications c
  cross apply dbo.split(c.attachment, ',') s
) c
  on o.id = c.o_id

デモで SQL Fiddleを参照してください

フィールドの値をattachment正しい名前に置き換えるだけの場合は、Split関数を使用CTEして 1 つのステップで行うことができます。

;with cte as (
  select o.id,
    o.name,
    c.body
  from orders o
  left join 
  (
    select c.body, s.items as o_id
    from communications c
    cross apply dbo.split(c.attachment, ',') s
  ) c
    on o.id = c.o_id
)
select distinct c2.body,
  stuff((select distinct ', ' + c1.name
         from cte c1
         where c2.body = c1.body
         for XML path('')),1,1,'') attachment
from cte c2

デモで SQL Fiddle を参照してください

于 2012-10-04T16:47:47.630 に答える
1

他の人がコメントしているように、正しい解決策は、データベーススキーマを変更して、アトミックフィールドを持つ正規化されたスキーマを持つことです。

現在のスキーマの解決策は、最初に添付ファイル フィールドを注文番号のリストに分割することです。使用可能な複数の方法のいずれかを使用します。次のステップでは、結果を id の Orders テーブルと結合して結果を取得します。3 番目のステップは、名前を連結してリストに戻すことです。分割と結合の説明については、提供されているリンクを参照してください。

以下は、3 つのステップを実行するスニペットです。

WITH
-- Numbers table for split logic
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A, L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A, L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A, L2 AS B),
Numbers AS(SELECT ROW_NUMBER() OVER(ORDER BY c) AS n FROM L3),

-- The join query for step 2
bodyOrders AS
(SELECT body,        
       o1.name orderName
FROM   Numbers AS nums 
INNER JOIN Communication AS valueTable 
ON nums.n <= CONVERT(int, LEN(valueTable.attachment)) 
AND SUBSTRING(N',' + valueTable.attachment, n, 1) = N','
INNER JOIN Orders o1
ON LTRIM(RTRIM(SUBSTRING(valueTable.attachment, nums.n, 
   charindex(N',', valueTable.attachment + N',', nums.n) - nums.n))) = o1.id
)

-- Concatenation logic for step 3
SELECT  body,
stuff( (SELECT ','+ orderName
               FROM bodyOrders b2
               WHERE b2.body = b1.body 
               ORDER BY orderName
               FOR XML PATH(''), TYPE).value('.', 'varchar(5000)')
            ,1,1,'')
       AS orderNumbers
      FROM bodyOrders b1
      GROUP BY body;

このスニペットは、大規模なデータ セットに対してこれを行うための最適またはパフォーマンスの高い方法を提供していません。これは、この道をたどらなければならない場合の方法の例にすぎません。

例 SQL フィドル

于 2012-10-04T17:06:48.097 に答える