tsql:在join中选择子查询的替代方法

时间:2014-02-03 11:31:18

标签: sql sql-server

这是我简化的表格布局:

table1:pID(pkey),数据 table2:rowID(pkey),pID(fkey),数据,日期

我想从table1中选择一些行,每个pID从table2连接一行,以获取该pID的最新日期。 我目前使用以下查询执行此操作:

SELECT * FROM table1 as a
LEFT JOIN table2 AS b ON b.rowID = (SELECT TOP(1) rowID FROM table2 WHERE pID = a.pID ORDER BY date DESC)

这种工作方式很慢,可能是因为它必须在表1的每一行上做一个子查询。有没有办法改善这方面的性能或以另一种方式做?

5 个答案:

答案 0 :(得分:0)

使用下面的代码,并注意我按日期desc添加了订单以获取最新的数据

select *
from table1 a
inner join table2 b on a.pID=b.pID
where b.rowID in(select top(1) from table2 t where t.pID=a.pID order by Date desc)

答案 1 :(得分:0)

你可以在这些行上尝试一些东西,使用子查询根据日期字段获取最新信息(按pID分组),然后将其与第一个表连接,这样就不必执行子查询对于 Table1的每个行,将产生更好的性能:

Select *
FROM Table1 a
INNER JOIN 
   (
    SELECT pID, Max(Date) FROM Table2
    GROUP BY pID
   ) b
ON a.pID = b.pID

我使用 group by 为一列提供了示例SQL,如果您需要其他列,请将它们添加到GROUP BY子句中。希望这会有所帮助。

答案 2 :(得分:0)

使用ROW_NUMBER()函数获取一个列,说明表2中每行的哪个id是第一个(由pID分区,并由rowDate降序排序)

示例:

WITH cte AS 
(
  SELECT 
    rowID AS t2RowId, 
    ROW_NUMBER OVER (PARTITION BY pID ORDER BY rowDate DESC) AS rowNum
  FROM table2 t2
) -- gets the t2RowIds + a column which says which is the latest for each pID
SELECT t1.*, t2.* 
FROM table1 t1
LEFT JOIN 
(
  table2 t2
  JOIN cte ON t2.rowID = cte.t2RowId AND cte.rowNum = 1
) ON t1.pID = t2.pID

这保证每个pID只返回table2中的1个项目,即使多个项目具有相同的日期。您当然应该确保在表2中索引日期列以获得快速性能(理想情况下,该索引也涵盖了table2的PrimaryID)

答案 3 :(得分:0)

我在类似的情感中使用下面的代码(我将其转录为您的示例)

SELECT b.*
FROM table1 AS a
left outer join (
    SELECT a.*
    FROM table2 a
        inner join (
            SELECT a.pID, max(date) as date 
            FROM table2
            WHERE date <= <max_date>
            group by pID
            ) b ON a.pID = b.pID AND a.date = b.date
        ) b ON a.pID = b.pID
) b on a.pID = b.pID

这种方法的唯一问题是你必须确保日期不会为pID重新定位

答案 4 :(得分:0)

您可以使用row_number()函数和子查询执行此操作:

SELECT t1.* 
FROM table1 t1 LEFT JOIN
     (select t2.*, row_number() over (partition by pId order by rowId desc) as seqnum
      from table2 t2
     ) t2
     on t1.pId = t2.pId and t2.seqnum = 1;