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 个字符。

我希望(或者我应该说我想要)得到这个。

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 回答