2

parent/child関係の次のサンプル テーブル構造があります。

parentテーブル

id    ShortText
--------------
10    
20    

childテーブル

id    char     value    order
-----------------------------
10    COLOR    RED      1
10    HEIGHT   1FT      2
10    LENGTH   10FT     5
20    COLOR    BLUE     1
20    WEIGHT   100LBS   3
20    WIDTH    2FT      4

子テーブルの行の特定のフィールドを連結して親テーブルのフィールドに配置する必要があることを指定する要件がありますShortText。フィールドはShortText最大 10 文字です。

私はこれを手に入れることを期待しています(または I WANTと言うべきです)。

id    ShortText
---------------
10    RED,1FT,
20    BLUE,2FT,

可能であれば、単一の SQL クエリでこれを完了したいと考えています。これを行う方法と、各子レコード セットの反復処理を回避する方法について何か提案はありますか? どんな助けでも大歓迎です!


これが私がこれまでに試したことです。

次の更新ステートメント...

UPDATE
  parent
SET
  ShortText = COALESCE(ShortText, N'') + 
           CASE WHEN DATALENGTH(COALESCE(ShortText, N'') + child.val + ',')/2 < 10
                THEN COALESCE(ShortText, N'') + child.val + ',' ELSE N'' END
FROM
  parent INNER JOIN child
    ON
      parent.id = child.id

しかし、私は次の結果しか得られません。

id    ShortText
------------------
10    RED,
20    BLUE,

私も次のことを試しましたが、長さをチェックしている case ステートメントが子テーブルの各行では実行されず、前の ShortText でのみ実行されるため、失敗しました。

UPDATE
    p
SET
    p.ShortText = p.ShortText +
        STUFF((
        SELECT
            CASE WHEN 
                    DATALENGTH(p.ShortText)/2 + DATALENGTH(c.val + N',')/2 < 10
                THEN
                    c.val + N','
                ELSE
                    N''
                END
        FROM
            child as c
        WHERE
            c.id = p.id
        FOR XML PATH(''), type).value('.','NVARCHAR(max)'), 1, 0, N'')
FROM
    parent as p

参照用のSQLfiddleを次に示します。こちらにも同様の質問を投稿して回答を得ましたが、これは別の要件であり、長さの要件に合わせてスケーリングすることはできません。いつものように、どんな助けも大歓迎です。

4

1 に答える 1

2

NULL の p.ShortText を確認してから、派生テーブルを更新します

UPDATE x
SET x.ShortText = NewShortText
FROM (SELECT p.ShortText, STUFF((SELECT CASE WHEN 
                          DATALENGTH(ISNULL(p.ShortText, ''))/2 +  DATALENGTH(ISNULL(c.value, '') + N',')/2 < 10
                                             THEN c.value + N','
                                             ELSE N'' END
FROM child as c
WHERE c.id = p.id
FOR XML PATH(''), type).value('.','NVARCHAR(max)'), 1, 0, N'') AS NewShortText 
FROM parent as p) x

更新 14.11.2012

;WITH cte (id, uid, val)
AS
 (
  SELECT ROW_NUMBER() OVER(PARTITION BY p.[uid] ORDER BY c.val DESC),
         p.uid, c.val
  FROM parent p INNER JOIN child c ON p.uid = c.uid
  ), cte2 (id, uid, val)
AS
 (  
  SELECT id, uid, val
  FROM cte
  WHERE id = 1 
  UNION ALL
  SELECT c.id, c.uid, CAST(ISNULL(ct.val, '') + ', ' + ISNULL(c.val, '') AS nvarchar(100)) AS val
  FROM cte c JOIN cte2 ct ON c.id = ct.id + 1 AND c.uid = ct.uid
)
UPDATE x
SET x.ShortText = x.MaxNewShortText
FROM
 (
  SELECT p.uid, p.ShortText, CASE WHEN DATALENGTH(val)/2 < 10
                                  THEN val END AS NewShortText,
  MAX(CASE WHEN DATALENGTH(val)/2 < 10
           THEN val END)
  OVER(PARTITION BY p.[uid]) AS MaxNewShortText
  FROM parent p JOIN cte2 ct ON p.uid = ct.uid
  ) x

SQLFiddle のデモ

于 2012-11-13T08:25:35.870 に答える