[英]SQL select MAX to find single record of a group
I have many records that represent the same information, but with different keys to other tables. 我有很多记录代表相同的信息,但是其他表的键不同。 I need to group these records by their common attributes (Att1, Att2, Att3), then select a single RecordID of all the common records to be the masterID for those common records.
我需要按它们的公共属性(Att1,Att2,Att3)对这些记录进行分组,然后从所有公共记录中选择一个RecordID作为这些公共记录的masterID。 That masterID needs to be added to each record that it represents, only if the masterID is null.
仅当masterID为null时,才需要将该masterID添加到它表示的每个记录中。 I cannot change the data structure and all table values are GUID.
我无法更改数据结构,并且所有表值都是GUID。 I have tried MAX, but I dont get the grouping.
我尝试过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
UPDATE: Added expected result. 更新:添加了预期的结果。
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
Yuck, I dislike this setup. uck,我不喜欢这种设置。 You're violating good normalization practices, and there's some inherent assumptions that require 'outside' knowledge.
您违反了良好的规范化实践,并且有一些固有的假设需要“外部”知识。 However, you've said you can't change it so...
但是,您说过不能更改它...
I believe the following should work (vendor neutral): 我认为以下方法应该有效(供应商中立):
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
Upon the revelation that GUIDs can be ordered, but cannot be passed for MIN()
or MAX()
(What?) - 得知可以排序GUID,但不能为
MIN()
或MAX()
传递GUID(什么?)-
You have (at least) three options: 您至少有三个选择:
SELECT MIN(CAST(b.recordId as CHAR(36)))
). SELECT MIN(CAST(b.recordId as CHAR(36)))
)。 However, this is likely to be poor performing, simply because it's going to cast every row (see, this is why it's preferrable for internal ids to be simple integers). Attempt this vendor-neutral statement: 尝试以下与供应商无关的声明:
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
There's also this more idiomatic version for SQL Server: 对于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
Try this: 尝试这个:
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
If you want to select only then you can use the following query - 如果只想选择,则可以使用以下查询-
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
You could use a cross apply to make a selection. 您可以使用交叉申请进行选择。 The cross apply basically selects the lowest RecordID that has matching Att1, Att2, and Att3 and joins the RecordID as a column named MasteRID.
交叉应用基本上选择具有匹配的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
The update will update each RecordID entry's MasterID column with the appropriate RecordID. 此更新将使用适当的RecordID更新每个RecordID条目的MasterID列。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.