我有一个查询,它使用两个JOIN,以这种格式返回一个列表:
unique_id | non_unique_id | timestamp
完整列表很大(数千行),查询结果只有几十行,因为查询的 WHERE时间戳> ='过去的某个时间戳'
所以现在,我有这样的清单:
89 | 286 | 1406219705
87 | 286 | 1406219518
79 | 922 | 1406216949
78 | 228 | 1406216871
77 | 126 | 1406216748
76 | 939 | 1406216722
74 | 126 | 1406216352
64 | 939 | 1406212540
63 | 126 | 1406212522
49 | 228 | 1406205715
48 | 228 | 1406204851
37 | 228 | 1406196435
32 | 228 | 1406190209
23 | 126 | 1406182577 <- 'limiting timestamp'
18 | 871 | 1406181991
10 | 922 | 1406178816
9 | 764 | 1406178778
7 | 609 | 1406178699
5 | 126 | 1406177398
4 | 871 | 1406177379 <- 'some timestamp in the past'
现在,我只需要在'限制时间戳'和列表末尾('过去的某个时间戳')之间选择行。我可以在原始查询的WHERE条件中指定'限制时间戳',但问题是:我需要结果集没有 non_unique_id 的记录,已经出现在'限制时间戳'上方的列表中。这是查询结果的样子:
<- 'limiting timestamp'
18 | 871 | 1406181991
9 | 764 | 1406178778
7 | 609 | 1406178699
<- 'some timestamp in the past'
因此,结果将返回3行,这些行都具有 non_unique_id ,这些行未出现在上面的结果中。但是如果'non_unique_id'已经出现在'限制时间戳'和'过去'中的某个时间戳之间的列表中,则只应保留第一次出现。注意:最后一部分条件是可选的,因为从最终列表中提取副本非常容易。
到目前为止,我只能提出在列表&gt; ='过去的某个时间戳和&gt;之间进行联接的解决方案。 '限制时间戳'。这样我就会看到底部列表中是否出现过顶部列表。但是,可以假设查询很复杂,生成结果所需的时间不应该再次运行加倍,但条件略有不同。
答案 0 :(得分:1)
试试这个:
SELECT *
FROM my_table AS t1
WHERE timestamp < @limiting_timestamp
AND timestamp > @some_timestamp_in_the_past
AND NOT EXISTS(SELECT 1
FROM my_table AS t2
WHERE timestamp > @limiting_timestamp
AND t1.non_unique_id = t2.non_unique_id)
这将为您提供在限制时间戳之后未出现的时间戳之间的记录。请注意,如果您希望记录等于过滤时间戳,则可以使用between关键字而不是&lt;和&gt;。
要消除你可以使用另一个子查询:
AND t1.timestamp = (SELECT MAX(timestamp)
FROM my_table AS t2
WHERE timestamp < @limiting_timestamp
AND timestamp > @some_timestamp_in_the_past
GROUP BY unique_id)
答案 1 :(得分:1)
如果SQL Server 2008+(sqlfiddle:http://sqlfiddle.com/#!3/0bc33/3):
,您可以尝试此操作WITH cteOrdered
AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY t1.Non_Unique_ID ORDER BY t1.Timestamp) AS RID,
t1.*
FROM Table1 t1 LEFT JOIN
(SELECT Non_Unique_ID
FROM Table1
WHERE Timestamp < 1406177379 OR
Timestamp > 1406182577) t2
ON t1.Non_Unique_ID = t2.Non_Unique_ID
WHERE t2.Non_Unique_ID IS NULL AND
t1.Timestamp > 1406177379 AND
t1.Timestamp < 1406182577
)
SELECT Unique_ID,
Non_Unique_ID,
Timestamp
FROM cteOrdered
WHERE RID = 1;
我在数据中添加了另一行
(18, 871, 1406181990),
查看查询是否产生了您想要的内容。您说如果搜索范围内存在重复的non_unique_id,则只应保留“第一个”事件。我认为这是具有EARLIEST时间戳的那个?如果相反,您可以更改此行
SELECT ROW_NUMBER() OVER (PARTITION BY t1.Non_Unique_ID ORDER BY t1.Timestamp) AS RID,
到
SELECT ROW_NUMBER() OVER (PARTITION BY t1.Non_Unique_ID ORDER BY t1.Timestamp DESC) AS RID,
这将翻转顺序以保留重复项的最新时间戳。