我在SQL中寻找以下查询 - 即从表格中选择ID,其中条目在“最后一小时”内,最后签到值为“false”。
样本数据'Table1':
ID(int), Check-In(boolean), Name(nvarchar), Entry(DateTime)*, PersonID(int)
*DateTime Format: DD/MM/YYYY HH:MM:SS
1, true, Klaus, 14/05/2015 15:45:21, 100
2, true, Klaus, 14/05/2015 16:05:22, 100
3, false, Klaus, 14/05/2015 16:06:04, 100
4, true, Pete, 14/05/2015 16:20:33, 101
5, false, Michelle, 14/05/2015 16:24:22, 105
6, true, Pete, 14/05/2015 16:25:55, 101
7, false, Pete, 14/05/2015 16:28:44, 101
8, true, Pete, 14/05/2015 16:29:36, 101
查询结果:
从Table1中选择ID,其中time = last_hour和(LAST)Check-In为false'
= 3和5(不要选择7)
在上面的例子中,我不想选择ID 7,因为Pete的最后一次登记是真的(ID 8)。
我是如何通过SQL查询实现这一目标的?这可以通过简单的查询来实现吗?
答案 0 :(得分:3)
要确保最后签入为false
,您必须检查表格中是否有较新的行。
你可以用“不存在”条款来做到这一点。
试试这个:
select * from table1 t1
where entry > DATE_SUB(NOW(), INTERVAL 1 HOUR)
and checkin = false
and not exists (
select * from table1 t2
where t2.name = t1.name
and t2.entry > t1.entry)
答案 1 :(得分:2)
这是使用partition
的另一种方式。我现在无法解释。但我的猜测是这个版本的扫描次数要少于每行exists
。
注意小提琴没有1小时的验证
sql server位字段也是(0,1)不是(false,true)
row = 1
:选择每个用户的最后一个条目CheckIn = 0
是CheckIn = False
WITH last_entry as (
SELECT *, ROW_NUMBER() OVER(PARTITION BY Name ORDER BY Entry DESC) AS row
FROM table1
WHERE entry > DATE_SUB(NOW(), INTERVAL 1 HOUR)
)
SELECT *
FROM last_entry
WHERE
row = 1
and CheckIn = 0
答案 2 :(得分:1)
如果您使用SQL Server 2012+来确定它是否是上次错误尝试,请使用LEAD
。
<强> Demo SqlFiddle 强>
CREATE TABLE tab(
Id INT
,Check_in BIT /* BIT 0 - false, 1 - true) */
,Name NVARCHAR(10)
,Entry DATETIME
,PersonId INT)
SET DATEFORMAT dmy;
INSERT INTO tab(Id, Check_in, Name, Entry, PersonId)
SELECT 1, 1, 'Klaus', '14/05/2015 15:45:21', 100 UNION ALL
SELECT 2, 1, 'Klaus', '14/05/2015 16:05:22', 100 UNION ALL
SELECT 3, 0, 'Klaus', '14/05/2015 16:06:04', 100 UNION ALL
SELECT 4, 1, 'Pete', '14/05/2015 16:20:33', 101 UNION ALL
SELECT 5, 0, 'Michelle', '14/05/2015 16:24:22',105 UNION ALL
SELECT 6, 1, 'Pete', '14/05/2015 16:25:55', 101 UNION ALL
SELECT 7, 0, 'Pete', '14/05/2015 16:28:44', 101 UNION ALL
SELECT 8, 1, 'Pete', '14/05/2015 16:29:36', 101
WITH cte(Id, Next_id, Entry, Name, Check_in, PersonId)
AS
(
SELECT
Id
,LEAD(id, 1, NULL) OVER ( PARTITION BY Name ORDER BY Entry )
,Entry
,Name
,Check_in
,PersonId
FROM tab
WHERE DATEDIFF(minute, Entry, GETDATE()) < 60
)
SELECT Id, Entry, Name, Check_in, PersonId
FROM cte
WHERE check_in = 0
AND [Next_id] IS NULL;