2015-08-20 34 views
1

我有一个约会数据库,每个约会都有一个人名,序号,约会日期和两个问卷调查分数。从约会列表中选择第一个和最后一个分数

我需要做的是为每个人物带回一行,显示他们与分数的第一次约会,以及他们上次与分数的约会,以及两者的分数。

在花了很长一段时间已经在什么可能是一个非常简单的查询,我试图使用以下方法来只是给我的第预约得分:

SELECT 
PERSONID, 
MIN(CONTACTDATE) AS 'FIRST_CONTACT', 
QUEST_1, 
QUEST_2 

FROM TBL_APPOINTMENTS 

GROUP BY 
PERSONID, 
CONTACTDATE, 
QUEST_1, 
QUEST_2 

ORDER BY 
PERSONID, 
FIRST_CONTACT 

正如你可能已经猜到了,每当QUEST_1或QUEST_2中的值发生更改时,这会给我重复的行。

任何人都可以帮忙吗?我相信这一切都很简单,但是它让我感动不已!

在此先感谢!

+0

的样本数据会有所帮助。特别是,这应该增加什么? “,以及” –

+0

“的分数,你的意思是当你选择一行时,它的上一行和下一行也被选中,三行返回? –

+0

如何在单行中添加Q1和Q2,即从表中SELECT QUEST_1 +','+ QUEST_2 AS QUEST。 这是我明白的问题是。 – aadi

回答

1

如果你正在寻找的结果是这样的:

PERSONID FIRST_CONTACT FIRST_QUEST_1 FIRST_QUEST_2 LAST_CONTACT LAST_QUEST_1 LAST_QUEST_2 
----------- ------------- ------------- ------------- ------------ ------------ ------------ 
1   2015-01-01 10   11   2015-01-21 21   211 
2   2015-01-01 11   24   2015-01-31 12   25 
3   2015-02-01 13   21   2015-03-01 14   28 
4   2015-03-01 15   29   2015-04-01 16   21 

然后将下面的查询会这样想的。请注意,如果一个人只有一条记录,则最大和最小日期和分数将是相同的。

SELECT 
    PERSONID, 
    FIRST_CONTACT, FIRST_QUEST_1, FIRST_QUEST_2, 
    LAST_CONTACT, LAST_QUEST_1, LAST_QUEST_2 
FROM (
    SELECT PERSONID, MIN(CONTACTDATE) AS 'FIRST_CONTACT', MAX(CONTACTDATE) AS 'LAST_CONTACT' 
    FROM TBL_APPOINTMENTS a 
    GROUP BY PERSONID 
) a 
CROSS APPLY (
    SELECT QUEST_1 AS 'FIRST_QUEST_1', QUEST_2 AS 'FIRST_QUEST_2' 
    FROM TBL_APPOINTMENTS 
    WHERE PERSONID = a.PERSONID AND CONTACTDATE = A.FIRST_CONTACT 
) o_first 
CROSS APPLY (
    SELECT QUEST_1 AS 'LAST_QUEST_1', QUEST_2 AS 'LAST_QUEST_2' 
    FROM TBL_APPOINTMENTS 
    WHERE PERSONID = a.PERSONID AND CONTACTDATE = A.LAST_CONTACT 
) o_last 
ORDER BY PERSONID, FIRST_CONTACT; 

同样的查询可以用写联接:

SELECT 
    A.PERSONID, 
    FIRST_CONTACT, 
    F.QUEST_1 AS FIRST_QUEST_1, 
    F.QUEST_2 AS FIRST_QUEST_2, 
    LAST_CONTACT, 
    L.QUEST_1 AS LAST_QUEST_1, 
    L.QUEST_2 AS LAST_QUEST_2 
FROM (
    SELECT PERSONID, MIN(CONTACTDATE) AS 'FIRST_CONTACT', MAX(CONTACTDATE) AS 'LAST_CONTACT' 
    FROM TBL_APPOINTMENTS a 
    GROUP BY PERSONID 
) a 
JOIN TBL_APPOINTMENTS F ON F.PERSONID = a.PERSONID AND A.FIRST_CONTACT = F.CONTACTDATE 
JOIN TBL_APPOINTMENTS L ON L.PERSONID = a.PERSONID AND A.LAST_CONTACT = L.CONTACTDATE 
ORDER BY A.PERSONID, FIRST_CONTACT; 
+0

我不认为你需要在这里使用'APPLY'。你可以简单地加入到桌子上。*(对于这种情况,使用'APPLY'似乎更适合,如果它像'person OUTER APPLY(SELECT TOP 1 FROM WHERE person = person ORDER BY contactdate ASC)AS o_first'那样,以避免初始聚合过程通过约会表)。* – MatBailie

+0

@MatBailie是的,我只是认为它看起来更清洁与应用程序,因为代码减少了一点。这两个版本都在我的测试中生成了相同的执行计划,因此我认为两者都不应该更好地提高性能(尽管我的测试当然仅限于非常小的样本)。 – jpw

+0

你甚至不需要子查询。 '(聚合)左连接约会o_first ON blah左连接约会o_last ON blah'删除子查询应该使它更加整洁。 – MatBailie

0
SELECT PERSONID, 
    MIN(CONTACTDATE) AS 'FIRST_CONTACT', MAX(CONTACTDATE) AS 'LAST_CONTACT' 
    QUEST_1, 
    QUEST_2 
    FROM TBL_APPOINTMENTS 
    GROUP BY PERSONID, 
CONTACTDATE, 
QUEST_1, 
QUEST_2 
ORDER BY 
    PERSONID, 
    FIRST_CONTACT 
+0

您错过了'FROM'子句。而在SQL SERVER中,你不能选择'QUEST_1'或'QUEST_2',因为它们不在'GROUP BY'子句中。 – MatBailie

+0

@MatBailie对不起,这只是一个错字 – user3804193

1

使用ROW_NUMBER()您可以分配约会从1在每PERSONID基础开始连续值。

在下面的例子中,我创建了两个这样的序数,一个在时间上向前,另一个在时间上反向。那么我可以选择first going forward以及first going backwards

WITH 
    sorted AS 
(
    SELECT 
    PERSONID, 
    CONTACTDATE, 
    QUEST_1, 
    QUEST_2, 
    ROW_NUMBER() OVER (PARTITION BY PERSONID ORDER BY CONTACTDATE ASC) AS ORD_FWD, 
    ROW_NUMBER() OVER (PARTITION BY PERSONID ORDER BY CONTACTDATE DESC) AS ORD_REV 
    FROM 
    TBL_APPOINTMENTS 
) 
SELECT 
    PERSONID, 
    CONTACTDATE, 
    QUEST_1, 
    QUEST_2 
FROM 
    sorted 
WHERE 
    ORD_FWD = 1 OR ORD_REV = 1 
ORDER BY 
    PERSONID, 
    CONTACTDATE 

编辑随着第一和最后到一个行汇总...

WITH 
    sorted AS 
(
    SELECT 
    PERSONID, 
    CONTACTDATE, 
    QUEST_1, 
    QUEST_2, 
    ROW_NUMBER() OVER (PARTITION BY PERSONID ORDER BY CONTACTDATE ASC) AS ORD_FWD, 
    ROW_NUMBER() OVER (PARTITION BY PERSONID ORDER BY CONTACTDATE DESC) AS ORD_REV 
    FROM 
    TBL_APPOINTMENTS 
) 
SELECT 
    PERSONID, 
    MAX(CASE WHEN ORD_FWD = 1 THEN CONTACTDATE END) AS FIRST_CONTACTDATE, 
    MAX(CASE WHEN ORD_FWD = 1 THEN QUEST_1  END) AS FIRST_QUEST_1, 
    MAX(CASE WHEN ORD_FWD = 1 THEN QUEST_2  END) AS FIRST_QUEST_2, 
    MAX(CASE WHEN ORD_REV = 1 THEN CONTACTDATE END) AS FINAL_CONTACTDATE, 
    MAX(CASE WHEN ORD_REV = 1 THEN QUEST_1  END) AS FINAL_QUEST_1, 
    MAX(CASE WHEN ORD_REV = 1 THEN QUEST_2  END) AS FINAL_QUEST_2 
FROM 
    sorted 
WHERE 
    ORD_FWD = 1 OR ORD_REV = 1 
GROUP BY 
    PERSONID 
ORDER BY 
    PERSONID 

注意:这可能是第一个和最后一个约会是相同的任命(如果该人只有一个预约)

相关问题