我有一个简单的表格,其中包含“读者”对象的状态历史记录。州可以是主动或非主动。现在我想有一个查询,它会选择所有读者,这些读者在给定时期内处于活动状态。下图显示了我的意思:带有绿色“生命线”的“读者”在显示的时间段内处于活动状态;所以它们将在查询中返回。
表格ReaderActivity
看起来像这样(仅限示例,不匹配上图):
reader_id | state | timestamp
1 | ACTIVE | 1467331201089
2 | ACTIVE | 1467332454545
1 | INACTIVE | 1467348875254
3 | ACTIVE | 1467350416546
1 | ACTIVE | 1467351871123
2 | INACTIVE | 1467352111545
当然,Reader
映射到的reader_id
个实体。
我需要有一个JPA查询,但我有问题,包括读者进入结果,在此期间内没有“上升边缘”(状态从INACTIVE变为ACTIVE)(在此期间已经有效)我们调查)。
我基本上看到了查询的部分内容:
SELECT DISTINCT a.reader FROM ReaderActivity a WHERE a.timestamp >= :startTimestamp AND a.timestamp < :endTimestamp AND a.state = 'ACTIVE'
SELECT DISTINCT a.reader FROM ReaderActivity a WHERE a.timestamp >= :startTimestamp AND a.timestamp < :endTimestamp AND a.state = 'ACTIVE' or (SELECT aa.reader FROM ReaderActivity aa where aa.reader = a.reader AND aa.timestamp < :startTimestamp AND aa.state = 'ACTIVE' GROUP BY aa.reader ORDER BY max(aa.timestamp)) != null
这也返回上图中红色标记的阅读器,因为在子查询中使用AND aa.state = 'ACTIVE'
,我们已经过滤掉所有ACTIVE状态,因此最后一个当然是ACTIVE。我应该在开始时段之前选择最后一个状态,然后检查它是否为ACTIVE。但是如何?
有人能把我带到正确的路上吗? 提前致谢!
答案 0 :(得分:1)
此查询应该这样做:
SELECT r.reader_id, r.timestamp
FROM ReaderActivity r
WHERE r.timestamp>=:start AND
r.timestamp<=:stop AND
r.state='ACTIVE'
UNION ALL
SELECT r1.reader_id, r1.timestamp
FROM ReaderActivity r1
LEFT JOIN ReaderActivity r2 ON (r2.reader_id = r1.reader_id AND
r2.timestamp<:start AND
r2.timestamp>r1.timestamp)
WHERE r1.timestamp<:start AND
r1.state='ACTIVE' AND
r2.id IS NULL
UNION的fisrt部分选择在该时间段内激活的读者,而UNION的第二部分仅选择在该时间段之前激活的读者。
我没有测试过查询,你可能需要调整一下。
答案 1 :(得分:1)
查询的第一部分将根据需要将状态更改为活动状态的记录恢复为活动状态。查询的第二部分需要进行一些改进。
要做你想要的事情,你将不得不为每个reader_id带回最近的状态变化,直到&#34; startTimeStamp&#34;。然后,您将从中选择那些列为&#34; ACTIVE&#34;那个时候。
像...这样的东西。
Select a.reader_id
From ReaderActivity a
Where a.timeStamp in
(
Select max(b.timeStamp)
From ReaderActivity b
Where b.timestamp < :startTimeStamp
And b.reader_id = a.reader_id
Group By b.reader_id
)
and a.state = "ACTIVE"
此查询将返回在指定时间段开始时处于活动状态的所有[reader_id]。您可以在原始查询的where子句中运行它,或者您可以使用UNION将其附加到查询的末尾,并在整个混乱中运行Select Distinct(reader_id)。
从表中的组的最大值中选择对我来说总是有点古怪。但我希望这个查询有帮助!