由一些领域分组并与其他人联系

时间:2014-12-01 17:49:46

标签: sql sql-server tsql

我正在比较2张桌子。一个有新数据,另一个有上个月的旧数据。数据每月发布一次,每次都是数据。没有PK,任何字段都可以改变。我需要显示更改记录的字段和旧值。它可以是1个或多个字段。为此,我创建了内连接,其中所有字段都连接在一起,除了1然后在我说旧值不等于新值的地方然后我添加2列,告诉我我们正在查看哪个字段以及旧的价值是。我对每个字段执行此查询并将结果合并,因此我的最终表格如下所示:

FieldA, FieldB, FieldC, FieldChanged, OldValue

FieldChanged将为该记录更改字段名称,OldValue将说明旧值是什么。

如果记录中有多个字段已更改(有),那么我会在结果中复制字段A-C,并使用不同的FieldChanged和OldValue值。但是,我想通过FieldA,FieldB,FieldC做一个小组,并以某种方式联系所有相同记录中的FieldChanged和来自所有相同记录的OldValue。

联合查询结果看起来像(前三个字段是新数据的样子):

"Tiger", "74", "Masters", "FieldC", "The Masters"
"Tiger", "74", "Masters", "FieldB", "68"

我想按字段1-3进行分组,然后连接组中的最后两个字段:

"Tiger", "74", "Masters", "FieldB,FieldC", "68,The Masters"

现在这只是一个例子,所以它很简单,可能很容易说这是一个新的记录,但是我的表有12个字段,所以如果一切都匹配但只有1个字段,很可能它是相同的记录,他们只是更新了一个的领域。

此处的关键是能够按某些列进行分组,并将分组列中的其他字段值连接在一起,以便不重复相同的记录,并且我有1行显示已为该记录更改的每个字段,它是旧的价值观。

1 个答案:

答案 0 :(得分:2)

试试这个。

CREATE TABLE #test
  (
     FieldA       VARCHAR(25),
     FieldB       VARCHAR(25),
     FieldC       VARCHAR(25),
     FieldChanged VARCHAR(25),
     OldValue     VARCHAR(25)
  )

INSERT #test
VALUES ('Tiger','74','Masters','FieldC','The Masters'),
       ('Tiger','74','Masters','FieldB','68')

方法1:适用于XML PATH

SELECT my_column AS [text()] 
FROM   my_table 
FOR XML PATH('')

这为您提供了表

中此列的所有值的连接值
SELECT FieldA,
       FieldB,
       FieldC,
       Stuff((SELECT ', ' + FieldChanged
              FROM   #test b
              WHERE  b.FieldA = a.FieldA
                     AND b.FieldB = a.FieldB
                     AND b.FieldC = a.FieldC
              FOR XML PATH('')), 1, 2, '') FieldChanged,
       Stuff((SELECT ', ' + OldValue
              FROM   #test b
              WHERE  b.FieldA = a.FieldA
                     AND b.FieldB = a.FieldB
                     AND b.FieldC = a.FieldC
              FOR XML PATH('')), 1, 2, '') OldValue
FROM   #test a
GROUP  BY FieldA,
          FieldB,
          FieldC 

方法2:使用Cross Apply

SELECT FieldA,
       FieldB,
       FieldC,
       Substring(d.FieldChanged, 1, Len(d.FieldChanged) - 1) FieldChanged,
       Substring(d.OldValue, 1, Len(d.OldValue) - 1)         OldValue
FROM   (SELECT DISTINCT FieldA,
                        FieldB,
                        FieldC
        FROM   #test) a
       CROSS APPLY (SELECT (SELECT FieldChanged + ', '
                            FROM   #test AS B
                            WHERE  b.FieldA = a.FieldA
                                   AND b.FieldB = a.FieldB
                                   AND b.FieldC = a.FieldC
                            FOR XML PATH('')),
                           (SELECT OldValue + ', '
                            FROM   #test AS B
                            WHERE  b.FieldA = a.FieldA
                                   AND b.FieldB = a.FieldB
                                   AND b.FieldC = a.FieldC
                            FOR XML PATH(''))) D (FieldChanged, OldValue)