繁体   English   中英

SQL选择MAX查找组的单个记录

[英]SQL select MAX to find single record of a group

我有很多记录代表相同的信息,但是其他表的键不同。 我需要按它们的公共属性(Att1,Att2,Att3)对这些记录进行分组,然后从所有公共记录中选择一个RecordID作为这些公共记录的masterID。 仅当masterID为null时,才需要将该masterID添加到它表示的每个记录中。 我无法更改数据结构,并且所有表值都是GUID。 我尝试过MAX,但没有得到分组。

TableA (Current State)

RecordID          Att1         Att2     Att3     MasterID
1                 A            B        C        
2                 A            B        C
3                 A            B        C
4                 D            E        F
5                 D            E        F
6                 D            E        F
7                 G            H        I         7
8                 G            H        I         7
9                 G            H        I         7

更新:添加了预期的结果。

TableA (Expected Result)

RecordID          Att1         Att2     Att3     MasterID
1                 A            B        C        1
2                 A            B        C        1
3                 A            B        C        1
4                 D            E        F        4
5                 D            E        F        4
6                 D            E        F        4
7                 G            H        I        7
8                 G            H        I        7
9                 G            H        I        7

uck,我不喜欢这种设置。 您违反了良好的规范化实践,并且有一些固有的假设需要“外部”知识。 但是,您说过不能更改它...

我认为以下方法应该有效(供应商中立):

UPDATE TableA as a SET masterId = (SELECT MIN(b.recordId) 
                                   FROM TableA as b
                                   WHERE b.att1 = a.att1
                                   AND b.att2 = a.att2
                                   AND b.att3 = a.att3)
WHERE masterId IS NULL


编辑:

得知可以排序GUID,但不能为MIN()MAX()传递GUID(什么?)-

您至少有三个选择:

  1. 将GUID强制转换为可传递的类型(即SELECT MIN(CAST(b.recordId as CHAR(36))) )。 但是,这可能表现不佳,仅是因为它将强制转换每一行(请参阅这就是为什么内部ID最好是简单整数的原因)。
  2. 尝试以下与供应商无关的声明:

     UPDATE TableA as a SET masterId = (SELECT b.recordId FROM TableA as b LEFT JOIN TableA as c ON c.att1 = b.att1 AND c.att2 = b.att2 AND c.att3 = b.att3 AND c.recordId < b.recordId WHERE b.att1 = a.att1 AND b.att2 = a.att2 AND b.att3 = a.att3 AND b.recordId <= a.recordId AND c.recordId IS NULL) WHERE masterId IS NULL 
  3. 对于SQL Server,还有一个更惯用的版本:

     UPDATE Updating SET Updating.masterId = Origin.recordId FROM TableA Updating JOIN (TableA Origin LEFT JOIN TableA Exclusion ON Exclusion.att1 = Origin.att1 AND Exclusion.att2 = Origin.att2 AND Exclusion.att3 = Origin.att3 AND Exclusion.recordId < Origin.recordId) ON Exclusion.recordId IS NULL AND Origin.att1 = Updating.att1 AND Origin.att2 = Updating.att2 AND Origin.att3 = Updating.att3 WHERE Updating.masterId IS NULL 

    SQL Fiddle示例

尝试这个:

UPDATE m
SET
    MasterID = s.RecordID
FROM TableA AS m
INNER JOIN (
    SELECT Att1, Att2, Att3, MIN(RecordID) AS RecordID          
    FROM TableA 
    GROUP BY Att1, Att2, Att3
) AS s
    ON m.Att1 = s.Att1 AND m.Att2 = s.Att2 AND m.Att3 = s.Att3
WHERE
    MasterID  IS NULL

如果只想选择,则可以使用以下查询-

select recordid ,
       Att1,
       Att2,
       Att3,
       COALESCE( MasterID , (select min(a2.recordid) from tableA a2
                            where a2.Att1 = a1.Att1
                            and a2.Att2= a1.Att2
                            and a1.Att3 = a2.Att3))
from TableA a1

您可以使用交叉申请进行选择。 交叉应用基本上选择具有匹配的Att1,Att2和Att3的最低RecordID,并将RecordID作为名为MasteRID的列加入。

WITH temp as (SELECT RecordID, Att1, Att2, Att3, c.MasterID FROM dbo.TableA b
    CROSS APPLY (SELECT TOP 1 RecordID as MasterID 
    FROM dbo.TableA a 
    WHERE a.Att1=b.Att1 
    AND a.Att2=b.Att2 AND a.Att3=b.Att3 
    ORDER BY RecordID) c)

UPDATE TableA 
SET MasterID=t.MasterID
FROM temp t
WHERE RecordID=t.RecordID

此更新将使用适当的RecordID更新每个RecordID条目的MasterID列。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM