连接 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:与字符串连接相反-如何将字符串拆分为多个记录[重复]

T-SQL:与字符串连接相反-如何将字符串拆分为多条记录[重复]

使用 t-sql 仅加入“最新”记录

记录历史的 T-SQL 中的增量负载

T-sql 中的记录顺序随统计信息更新而变化

T-SQL While 循环和连接