2013-02-20 180 views
2

我的设置是我有两个表Study和Activity_History。活动在研究中进行,因此存在一对多的关系。在SQL子查询中使用多列

我希望能够在Activity_History表上运行一个SQL查询,这将使我获得活动和以前运行的活动。我目前有这样的:

SELECT 
     * 
FROM Activity_History AS A1 
LEFT JOIN Activity_History AS A2 
ON A2.Parent_Study_ID = 
(
    SELECT TOP 1 Parent_Study_ID 
    FROM Activity_History AS A3 
    WHERE A3.Parent_Study_ID = A1.Parent_Study_ID 
      AND A3.Activity_Date < A1.Activity_Date 
    ORDER BY Activity_Date DESC 
) 

这是行不通的。发生什么事是它拉动查询的Activity_Date方没有任何作用,它只是按照每行的降序日期顺序返回第一个匹配的Activity_Date。我认为这是因为在我的子查询中我在使用Activity_Date的地方,但这不在子查询select中。

感谢您的帮助!

+0

你可以请加表模式,列名 – dekdev 2013-02-20 18:17:25

+0

什么是“*这是行不通的*”是什么意思? – RBarryYoung 2013-02-20 18:20:41

+1

你不应该需要在你的'SELECT'中的WHERE中包含所有的列......你得到的错误是什么? – 2013-02-20 18:21:06

回答

3

我假设你使用的是SQL Server?如果是这样,那么这应该使用ROW_NUMBER():

WITH CTE AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY Parent_Study_Id ORDER BY Activity_Date) RN 
    FROM Activity_History 
    ) 
SELECT * 
FROM CTE T1 
    LEFT JOIN CTE T2 ON T1.RN = T2.RN+1 AND T1.Parent_Study_Id = T2.Parent_Study_Id 

这里是SQL Fiddle

+1

正确的表达式是'row_number()over(由parent_study_id按activity_date排序的分区)'。 – 2013-02-20 18:19:49

+0

@GordonLinoff - 谢谢,在原始查询中没有看到 - 在Fiddle上工作并且速度太快了!谢谢! – sgeddes 2013-02-20 18:21:35

+0

太棒了,效果很好。 Row_Number()是一个非常酷的功能。 – 2013-02-20 21:39:18

0

在SQLServer2005的,而不是+ LEFT JOIN你需要使用OUTER APPLY

SELECT * 
FROM Activity_History AS A1 OUTER APPLY ( 
             SELECT TOP 1 Parent_Study_ID 
             FROM Activity_History AS A2 
             WHERE A2.Parent_Study_ID = A1.Parent_Study_ID 
              AND A2.Activity_Date < A1.Activity_Date 
             ORDER BY A2.Activity_Date DESC 
             ) o