连接 T-SQL 中的***记录
Posted
技术标签:
【中文标题】连接 T-SQL 中的***记录【英文标题】:Joining top records in T-SQL 【发布时间】:2011-10-24 06:39:48 【问题描述】:SELECT MD.*, Contact.FirstName
FROM MerchantData MD
JOIN Merchant M ON M.MerchID = MD.MerchID
JOIN (SELECT TOP 1 * FROM Location WHERE Location.BusID = MD.BusID) L ON L.BusID=MD.BusID
AND L.Deleted = 0
JOIN Contact ON Contact.ContactID = L.PrincipalID
我正在使用 SQLSERVER 2008 并尝试编写此 SQL 语句。有时,busid 有多个位置,我只想加入第一个找到的位置。我在“Location.BusID = MD.BusID”部分出现错误,因为 MD.BusID 无法绑定。是否可以在此连接的嵌套选择语句中使用 MD 表,或者是否有其他方法可以完成此操作?
我打算将使用嵌套查询的数据放在列列表中,以便在那里直接获取联系人数据。
【问题讨论】:
【参考方案1】:我认为拥有完整结果集的子查询会更简单:
SELECT MD.*, Contact.FirstName
FROM MerchantData MD
JOIN Merchant M ON M.MerchID = MD.MerchID
JOIN (SELECT BusID, MAX(PrincipalID)
FROM Location
WHERE Deleted = 0
GROUP BY BusID) L ON L.BusID=MD.BusID
JOIN Contact ON Contact.ContactID = L.PrincipalID
JOIN
中的每个 BusID
仍然有一条记录,但它不相关。
【讨论】:
问题是MAX和第一个不一样 他只想要一个BusID
并且没有指定排序顺序。如果他愿意,添加排序标准很简单。
@JNK 问题是在这种情况下要求最大删除将不起作用,因为子选择后的 L.Deleted = 0
@t-clausen - 很好,我会更正查询。我们可以把这个条件放在内部选择上。
问题有同样的问题shug。看来你只是继承了它。【参考方案2】:
SELECT MD.*, Contact.FirstName
FROM MerchantData MD
JOIN Merchant M ON M.MerchID = MD.MerchID
CROSS APPLY (SELECT TOP 1 * FROM Location WHERE BusID = MD.BusID AND DELETED = 0) L
JOIN Contact ON Contact.ContactID = L.PrincipalID
【讨论】:
【参考方案3】:这是“每组前 n 个”问题的案例。这个问题将指导你:
SQL Server query select 1 from each sub-group
你会想做这样的事情:
SELECT MD.* ,
Contact.FirstName
FROM MerchantData MD
JOIN Merchant M ON M.MerchID = MD.MerchID
JOIN ( select * ,
seq = rank() over( partition by BusID order by BusID , ... )
from Location
where L.Deleted = 0
) L on L.BusID = MD.BusID
and seq = 1
JOIN Contact ON Contact.ContactID = L.PrincipalID
虚拟表表达式应为每个 BusID 最多返回 1 个位置(如果 BusID 没有未删除的位置,则为 0)。
【讨论】:
规定的要求是先看再删,和先删不一样。但是您的解决方案很优雅,并且您确实清楚地说明了它的作用。【参考方案4】:为了尝试找出我会尝试的错误。看看它是否可以匹配 Location.BusID = MD.BusID。
SELECT MD.*, Contact.FirstName
FROM MerchantData MD
JOIN Merchant M ON M.MerchID = MD.MerchID
JOIN Location On Location.BusID = MD.BusID
你不用*所以用
SELECT TOP 1 Location.BusID FROM Location WHERE Location.BusID = MD.BusID
一旦你的语法工作。
您确实知道,一旦您开始使用它,它只会匹配“第一”行,然后检查它是否被删除。问题是没有“第一”行的顺序是任意的。即使表上有聚集索引,如果没有 order by 子句,也无法保证排序。要获得可重复的答案,您需要排序。但是,如果您正在排序并且只想要顶行,那么 MAX 或 MIN 和一个组会更直接。
如果您只希望有一个或多个已删除位置的企业,那么以下方法应该可行,但您需要为分组依据细分列。如果两个删除的位置有不同的联系人姓名,那么它将分别报告。所以,这可能不是您想要的。
SELECT MD.col1, MD.col2, Contact.FirstName
FROM MerchantData MD
JOIN Merchant M ON M.MerchID = MD.MerchID
JOIN Location L
ON L.BusID = MD.BusID
AND L.Deleted = 0
JOIN Contact ON Contact.ContactID = L.PrincipalID
GROUP BY MD.col1, MD.col2, Contact.FirstName
【讨论】:
以上是关于连接 T-SQL 中的***记录的主要内容,如果未能解决你的问题,请参考以下文章
T-SQL:与字符串连接相反-如何将字符串拆分为多个记录[重复]