【问题标题】:How to select InTime and OutTime using SQL query如何使用 SQL 查询选择 InTime 和 OutTime
【发布时间】:2021-06-15 13:24:17
【问题描述】:

我有一个名为 tblEventRegister(Tagvalue int, EventDate datetime, TagName nvarchar(50), EventName nvarchar(50)) 的表。

该表有以下数据:

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

我怎样才能做到这一点?

【问题讨论】:

  • @DaleK 我已经提供了带有表定义及其列的示例数据,先生
  • 什么逻辑确定 2021-03-18 12:06:45.547EventDateTagValue 的行>02021-03-18 12:06:35.547EventDate 和 @987654329 的行对齐1 的@?有多个行具有相同的 TagNameEventName 值,因此除非您省略了一些信息,否则无法将它们放在一起
  • @SunnySandeep 我注意到你有很多未被接受的答案 - 我鼓励你重新审视它们并接受一些。

标签: sql sql-server tsql sql-server-2014


【解决方案1】:

以下内容返回您想要的结果...但请注意,它没有考虑任何其他可能的数据问题。所以它假设每个时间都会有一个匹配的时间,或者没有时间。但它不会处理多次进出时间。

它的工作原理是为每个 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;

返回:

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) 作为某种默认查询设置,因为结果可能出乎意料。仅当您完全了解后果并且绝对必须这样做时,才应使用该提示。

【讨论】:

  • 抱歉回复晚了,您的回答绝对没问题。只有一个问题,如果重复相同的值,比如 1 在 1 之后重复出现,那么最后一个 1 不应该重复显示。我们该如何处理。这个?
  • @SunnySandeep 抱歉,我没有关注...我认为最好提出一个新问题。
【解决方案2】:

如果我假设每个“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 是一个 dbfiddle。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-09
    • 2017-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多