如何使用 SQL 查询 select InTime 和 OutTime
How to select InTime and OutTime using SQL query
我有一个名为 tblEventRegister(Tagvalue int, EventDate datetime, TagName nvarchar(50), EventName nvarchar(50))
的 table。
table有以下数据:
EventDate TagName EventName TagValue
2021-03-18 12:06:35.547 A1 E1 1
2021-03-18 12:06:37.547 A2 E1 1
2021-03-18 12:06:38.547 A3 E1 1
2021-03-18 12:06:45.547 A1 E1 0
2021-03-18 12:06:47.547 A1 E1 0
2021-03-18 12:06:48.547 A1 E1 1
2021-03-18 12:06:55.547 A1 E1 0
2021-03-18 12:06:56.547 A1 E1 0
2021-03-18 12:06:57.547 A1 E1 1
当TagValue=1时EventDate为InTime,当tagvalue为0时EventDate为OutTime。我使用以下查询来查找 InTime 和 OutTime。
select EventDate, TagName, EventName, Tagvalue
, (case Tagvalue when 1 then EventDate end) intime
, (case Tagvalue when 0 then EventDate end) outtime
from tblEventRegister with (nolock)
结果来了
EventDate TagName EventName TagValue InTime OutTime
2021-03-18 12:06:35.547 A1 E1 1 2021-03-18 12:06:35.547 Null
2021-03-18 12:06:37.547 A2 E1 1 2021-03-18 12:06:37.547 Null
2021-03-18 12:06:38.547 A3 E1 1 2021-03-18 12:06:38.547 Null
2021-03-18 12:06:45.547 A1 E1 0 Null 2021-03-18 12:06:45.547
2021-03-18 12:06:47.547 A2 E1 0 Null 2021-03-18 12:06:47.547
2021-03-18 12:06:48.547 A1 E1 1 2021-03-18 12:06:48.547 Null
2021-03-18 12:06:55.547 A3 E1 0 Null 2021-03-18 12:06:55.547
2021-03-18 12:06:56.547 A1 E1 0 Null 2021-03-18 12:06:56.547
2021-03-18 12:06:57.547 A1 E1 1 2021-03-18 12:06:56.547 Null
但结果应该是
EventDate TagName EventName TagValue InTime OutTime
2021-03-18 12:06:35.547 A1 E1 1 2021-03-18 12:06:35.547 2021-03-18 12:06:45.547
2021-03-18 12:06:37.547 A2 E1 1 2021-03-18 12:06:37.547 2021-03-18 12:06:47.547
2021-03-18 12:06:38.547 A3 E1 1 2021-03-18 12:06:38.547 2021-03-18 12:06:55.547
2021-03-18 12:06:48.547 A1 E1 1 2021-03-18 12:06:48.547 2021-03-18 12:06:56.547
2021-03-18 12:06:57.547 A1 E1 1 2021-03-18 12:06:57.547 Null
我怎样才能做到这一点?
以下 returns 您想要的结果...但请注意,它没有考虑任何其他可能的数据问题。所以它假设每个时间都会有一个匹配的时间,或者没有时间。但它不会处理多个入站时间或出站时间。
它的工作原理是为每个 TagName、TagValue 对分配一个行号,然后将它们连接起来。
declare @tblEventRegister table (Tagvalue int, EventDate datetime, TagName nvarchar(50), EventName nvarchar(50));
insert into @tblEventRegister (EventDate, TagName, EventName, TagValue)
values
('2021-03-18 12:06:35.547', 'A1', 'E1', 1),
('2021-03-18 12:06:37.547', 'A2', 'E1', 1),
('2021-03-18 12:06:38.547', 'A3', 'E1', 1),
('2021-03-18 12:06:45.547', 'A1', 'E1', 0),
('2021-03-18 12:06:47.547', 'A2', 'E1', 0),
('2021-03-18 12:06:48.547', 'A1', 'E1', 1),
('2021-03-18 12:06:55.547', 'A3', 'E1', 0),
('2021-03-18 12:06:56.547', 'A1', 'E1', 0),
('2021-03-18 12:06:56.547', 'A1', 'E1', 1);
with cte as (
select *
, row_number() over (partition by TagName, TagValue order by EventDate) rn
from @tblEventRegister
)
select C1.EventDate, C1.TagName, C1.EventName, C1.TagValue, C1.Eventdate, C2.EventDate
from cte C1
left join cte C2 on C2.TagName = C1.TagName and C2.TagValue = 0 and C1.rn = C2.rn
where C1.TagValue = 1
order by C1.EventDate asc;
Returns:
EventDate
TagName
EventName
TagValue
Eventdate
EventDate
2021-03-18 12:06:35.547
A1
E1
1
2021-03-18 12:06:35.547
2021-03-18 12:06:45.547
2021-03-18 12:06:37.547
A2
E1
1
2021-03-18 12:06:37.547
2021-03-18 12:06:47.547
2021-03-18 12:06:38.547
A3
E1
1
2021-03-18 12:06:38.547
2021-03-18 12:06:55.547
2021-03-18 12:06:48.547
A1
E1
1
2021-03-18 12:06:48.547
2021-03-18 12:06:56.547
2021-03-18 12:06:56.547
A1
E1
1
2021-03-18 12:06:56.547
NULL
注 1:这显示了如何将您的样本数据呈现为 DDL+DML - 我鼓励您在将来包含它以获得更快的响应。
注意 2:不要将 with (nolock)
用作某种默认查询设置,因为结果可能出乎意料。只有当您完全理解后果并且您绝对必须这样做时,您才应该使用该提示。
如果我假设每个“in”后面最多跟着一个对应的“out”——也就是说,没有“in”后面跟着“in”或者“out”后面跟着“out” ,那么这道题就不难了。使用更脏的数据变得更加困难。
一种方法是简单地通过“in”和“out”枚举行,然后聚合:
select tagname, eventname, max(tagvalue), min(eventdate) as intime,
nullif(max(eventdate), min(eventdate)) as outtime
from (select er.*,
row_number() over (partition by tagname, eventname, tagvalue order by eventdate) as seqnum
from tblEventRegister er
) er
group by tagname, eventname, seqnum
order by intime;
nullif()
的目的是处理后面没有“out”的情况。
Here 是一个 db<>fiddle.
我有一个名为 tblEventRegister(Tagvalue int, EventDate datetime, TagName nvarchar(50), EventName nvarchar(50))
的 table。
table有以下数据:
EventDate TagName EventName TagValue
2021-03-18 12:06:35.547 A1 E1 1
2021-03-18 12:06:37.547 A2 E1 1
2021-03-18 12:06:38.547 A3 E1 1
2021-03-18 12:06:45.547 A1 E1 0
2021-03-18 12:06:47.547 A1 E1 0
2021-03-18 12:06:48.547 A1 E1 1
2021-03-18 12:06:55.547 A1 E1 0
2021-03-18 12:06:56.547 A1 E1 0
2021-03-18 12:06:57.547 A1 E1 1
当TagValue=1时EventDate为InTime,当tagvalue为0时EventDate为OutTime。我使用以下查询来查找 InTime 和 OutTime。
select EventDate, TagName, EventName, Tagvalue
, (case Tagvalue when 1 then EventDate end) intime
, (case Tagvalue when 0 then EventDate end) outtime
from tblEventRegister with (nolock)
结果来了
EventDate TagName EventName TagValue InTime OutTime
2021-03-18 12:06:35.547 A1 E1 1 2021-03-18 12:06:35.547 Null
2021-03-18 12:06:37.547 A2 E1 1 2021-03-18 12:06:37.547 Null
2021-03-18 12:06:38.547 A3 E1 1 2021-03-18 12:06:38.547 Null
2021-03-18 12:06:45.547 A1 E1 0 Null 2021-03-18 12:06:45.547
2021-03-18 12:06:47.547 A2 E1 0 Null 2021-03-18 12:06:47.547
2021-03-18 12:06:48.547 A1 E1 1 2021-03-18 12:06:48.547 Null
2021-03-18 12:06:55.547 A3 E1 0 Null 2021-03-18 12:06:55.547
2021-03-18 12:06:56.547 A1 E1 0 Null 2021-03-18 12:06:56.547
2021-03-18 12:06:57.547 A1 E1 1 2021-03-18 12:06:56.547 Null
但结果应该是
EventDate TagName EventName TagValue InTime OutTime
2021-03-18 12:06:35.547 A1 E1 1 2021-03-18 12:06:35.547 2021-03-18 12:06:45.547
2021-03-18 12:06:37.547 A2 E1 1 2021-03-18 12:06:37.547 2021-03-18 12:06:47.547
2021-03-18 12:06:38.547 A3 E1 1 2021-03-18 12:06:38.547 2021-03-18 12:06:55.547
2021-03-18 12:06:48.547 A1 E1 1 2021-03-18 12:06:48.547 2021-03-18 12:06:56.547
2021-03-18 12:06:57.547 A1 E1 1 2021-03-18 12:06:57.547 Null
我怎样才能做到这一点?
以下 returns 您想要的结果...但请注意,它没有考虑任何其他可能的数据问题。所以它假设每个时间都会有一个匹配的时间,或者没有时间。但它不会处理多个入站时间或出站时间。
它的工作原理是为每个 TagName、TagValue 对分配一个行号,然后将它们连接起来。
declare @tblEventRegister table (Tagvalue int, EventDate datetime, TagName nvarchar(50), EventName nvarchar(50));
insert into @tblEventRegister (EventDate, TagName, EventName, TagValue)
values
('2021-03-18 12:06:35.547', 'A1', 'E1', 1),
('2021-03-18 12:06:37.547', 'A2', 'E1', 1),
('2021-03-18 12:06:38.547', 'A3', 'E1', 1),
('2021-03-18 12:06:45.547', 'A1', 'E1', 0),
('2021-03-18 12:06:47.547', 'A2', 'E1', 0),
('2021-03-18 12:06:48.547', 'A1', 'E1', 1),
('2021-03-18 12:06:55.547', 'A3', 'E1', 0),
('2021-03-18 12:06:56.547', 'A1', 'E1', 0),
('2021-03-18 12:06:56.547', 'A1', 'E1', 1);
with cte as (
select *
, row_number() over (partition by TagName, TagValue order by EventDate) rn
from @tblEventRegister
)
select C1.EventDate, C1.TagName, C1.EventName, C1.TagValue, C1.Eventdate, C2.EventDate
from cte C1
left join cte C2 on C2.TagName = C1.TagName and C2.TagValue = 0 and C1.rn = C2.rn
where C1.TagValue = 1
order by C1.EventDate asc;
Returns:
EventDate | TagName | EventName | TagValue | Eventdate | EventDate |
---|---|---|---|---|---|
2021-03-18 12:06:35.547 | A1 | E1 | 1 | 2021-03-18 12:06:35.547 | 2021-03-18 12:06:45.547 |
2021-03-18 12:06:37.547 | A2 | E1 | 1 | 2021-03-18 12:06:37.547 | 2021-03-18 12:06:47.547 |
2021-03-18 12:06:38.547 | A3 | E1 | 1 | 2021-03-18 12:06:38.547 | 2021-03-18 12:06:55.547 |
2021-03-18 12:06:48.547 | A1 | E1 | 1 | 2021-03-18 12:06:48.547 | 2021-03-18 12:06:56.547 |
2021-03-18 12:06:56.547 | A1 | E1 | 1 | 2021-03-18 12:06:56.547 | NULL |
注 1:这显示了如何将您的样本数据呈现为 DDL+DML - 我鼓励您在将来包含它以获得更快的响应。
注意 2:不要将 with (nolock)
用作某种默认查询设置,因为结果可能出乎意料。只有当您完全理解后果并且您绝对必须这样做时,您才应该使用该提示。
如果我假设每个“in”后面最多跟着一个对应的“out”——也就是说,没有“in”后面跟着“in”或者“out”后面跟着“out” ,那么这道题就不难了。使用更脏的数据变得更加困难。
一种方法是简单地通过“in”和“out”枚举行,然后聚合:
select tagname, eventname, max(tagvalue), min(eventdate) as intime,
nullif(max(eventdate), min(eventdate)) as outtime
from (select er.*,
row_number() over (partition by tagname, eventname, tagvalue order by eventdate) as seqnum
from tblEventRegister er
) er
group by tagname, eventname, seqnum
order by intime;
nullif()
的目的是处理后面没有“out”的情况。
Here 是一个 db<>fiddle.