简体   繁体   English

仅在SQL Server中某个相应的列条件='y'之后才查询列条件='x'的行

[英]Query row where column condition = 'x' only after a certain corresponding column condition = 'y' in SQL Server

apologies in advance if I'm missing critical information, I'm very new to this. 如果我缺少重要信息,请提前道歉,这是我的新手。

I have a massive database of devices, receivers, and corresponding value that counts up one as messages are received. 我有一个庞大的设备,接收者数据库和相应的值数据库,这些值在收到消息时就累加一。

For example, here is my original table of data : 例如,这是我的原始数据表

+-----------------------+--------+-------+------------+-------+
|received_time          |receiver|device |message_type| value | 
+-----------------------+--------+-------+------------+-------+                                          
|2019-07-17 7:50:14.850 | R1     |     D1|      2     |   1   |
|2019-07-17 7:50:14.853 | R1     |     D1|      1     |  NULL | 
|2019-07-17 7:50:14.947 | R1     |     D1|      2     |   1   |
|2019-07-17 7:50:14.957 | R1     |     D1|      1     |  NULL |
|2019-07-17 7:50:15.060 | R2     |     D1|      2     |   1   | 
|2019-07-17 7:50:15.067 | R3     |     D1|      2     |   1   |
|2019-07-17 7:50:15.073 | R3     |     D1|      1     |  NULL |
|2019-07-17 7:50:15.170 | R4     |     D2|      1     |  NULL |
|2019-07-17 7:50:15.283 | R5     |     D2|      2     |   0   |
|2019-07-17 7:50:15.287 | R5     |     D2|      1     |  NULL |
|2019-07-17 7:55:00.000 | R1     |     D2|      5     |  NULL |  
|2019-07-17 7:55:01.400 | R1     |     D2|      2     |   A   |
+-----------------------+--------+-------+------------+-------+

and so on...

OBJECTIVE 目的

My objective is to query for the corresponding value only where a specific message_type is listed. 我的目标是仅在列出了特定的message_type情况下查询相应的值。 The problem is, this value is on a different row. 问题是,该值在另一行上。 This could be message_type = '5' , or message_type = '1' (whatever I'm currently looking for). 这可能是message_type = '5'message_type = '1' (无论我目前在寻找什么)。 The problem is, the only way I can think of to do this is by ordering by received_time but within a period of x seconds after the initial message_type condition has been met, however in some cases the '2' comes before the corresponding '1' message_type . 问题是,我唯一想到的方法是通过receive_time进行排序,但要在满足初始message_type条件后的x秒内进行排序,但是在某些情况下,“ 2”要比相应的“ 1”早message_type

I have already tried different variations of the GROUP BY function, but this has been very confusing and I'm not sure where to go from here. 我已经尝试过GROUP BY函数的不同变体,但这非常令人困惑,我不确定从这里开始。

Attempt #1 - Not good 尝试1-不好

SELECT received_time, receiver, device, message_type, value,
    CASE
        WHEN message_type = '5' THEN --Select corresponding value 
                                     --where message_type = '2'
    END 
FROM table;

Attempt #2 - closer to what I'm trying to do 尝试#2-接近我要去做的事

SELECT * FROM my_table
    WHERE message_type = '5' 
        SELECT * FROM my_table
            WHERE
                received_time BETWEEN (received_time - 3 seconds) 
                and (received_time + 3 seconds)
                and (device = device) --order by for each device?
                and (message_type = '5' or message_type = '2')

My expected table should look this if I want to search for message_type = 5: 如果我想搜索message_type = 5,则我的预期表应如下所示:

+-----------------------+--------+-------+------------+-------+
|received_time          |receiver|device |message_type| value | 
+-----------------------+--------+-------+------------+-------+                                          
|2019-07-17 7:55:00.000 | R1     |     D2|      5     |  NULL |
|2019-07-17 7:55:01.400 | R1     |     D2|      2     |   A   | 
+-----------------------+--------+-------+------------+-------+

But expected table should look this if I want to search for message_type = 1: 但是如果我想搜索message_type = 1,则预期表应该看起来像这样:

+-----------------------+--------+-------+------------+-------+
|received_time          |receiver|device |message_type| value | 
+-----------------------+--------+-------+------------+-------+                                          
|2019-07-17 7:50:14.850 | R1     |     D1|      2     |   1   |
|2019-07-17 7:50:14.853 | R1     |     D1|      1     |  NULL | 
|2019-07-17 7:50:15.170 | R4     |     D2|      1     |  NULL |
|2019-07-17 7:50:15.283 | R5     |     D2|      2     |   0   |
+-----------------------+--------+-------+------------+-------+

This is a very tricky question to ask, and hard to explain. 这是一个非常棘手的问题,很难解释。 Any help is much appreciated, thank you! 非常感谢您的帮助,谢谢!

As I understand your problem is that you need that for each message_type 1 or 5 find the corresponding message_type 2 and get the value, with the consideration that the type 2 could be before and after the type 1 or 5. The solution I am proposing here considers that the corresponding type 2 is the one closest to the original message (type 1 or 5). 据我了解,您的问题是您需要为每个message_type 1或5找到对应的message_type 2并获取值,并考虑到类型2可能在类型1或5之前和之后。我在这里提出的解决方案认为对应的类型2是最接近原始消息的类型(类型1或5)。

I do this in 2 steps: 我分两个步骤进行操作:

  1. Calculate which type 2 is closest to the one I want to find: 计算哪种类型2最接近我要查找的类型:

    select t2.receiver, t2.device, t2.received_time, MIN(ABS(DATEDIFF(MILLISECOND, t.received_time, t2.received_time))) AS closest_received_time INTO #tmpClosest from my_table as t inner join my_table as t2 ON t.receiver = t2.receiver and t.device = t2.device where t.message_type = 2 AND t2.message_type = 1 --define here the type for the main message (1 or 5) GROUP BY t2.receiver, t2.device, t2.received_time 选择t2.receiver,t2.device,t2.received_time,MIN(ABS(DATEDIFF(MILLISECOND,t.received_time,t2.received_time))))AS最接近时间INTO #tmp距离my_table最近,因为t内部加入my_table为t2 ON t.receiver = t2.receiver和t.device = t2.device,其中t.message_type = 2 AND t2.message_type = 1-在此定义主消息的类型(1或5)GROUP BY t2.receiver,t2.device,t2。接收时间

  2. With this temp table then you can retrieve the value for the corresponding one 使用此临时表,您可以检索对应的一个临时表的值。

    SELECT tc.receiver, tc.device, tc.received_time, t.value FROM #tmpClosest AS tc INNER JOIN my_table AS t ON t.receiver = tc.receiver AND t.device = tc.device WHERE tc.closest_received_time = ABS(DATEDIFF(MILLISECOND, t.received_time, tc.received_time)) SELECT tc.receiver,tc.device,tc.received_time,t.value from #tmpClosest AS tc INNER JOIN my_table AS t ON t.receiver = tc.receiver AND t.device = tc.device WHERE tc.closest_received_time = ABS(DATEDIFF (MILLISECOND,t.received_time,tc.received_time))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM