Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework query - select only record until timestamp from another table

I have 2 tables.

The 1st one is History table - data received by different devices.

+----------+-------------+--------------------+
| DeviceId | Temperature | TimeStamp          |
+----------+-------------+--------------------+
| 1        | 31          | 15.08.2020 1:42:00 |
| 2        | 40          | 15.08.2020 1:43:00 |
| 1        | 32          | 15.08.2020 1:44:00 |
| 1        | 34          | 15.08.2020 1:45:00 |
| 1        | 20          | 15.08.2020 1:46:00 |
| 2        | 45          | 15.08.2020 1:47:00 |
+----------+-------------+--------------------+

The 2nd one is DeviceStatusHistory table

+----------+---------+--------------------+
| DeviceId | Status  | TimeStamp          |
+----------+---------+--------------------+
| 1        | 1(OK)   | 15.08.2020 1:42:00 |
| 2        | 1(OK)   | 15.08.2020 1:43:00 |
| 1        | 1(OK)   | 15.08.2020 1:44:00 |
| 1        | 0(FAIL) | 15.08.2020 1:44:30 |
| 1        | 0(FAIL) | 15.08.2020 1:46:00 |
| 2        | 0(FAIL) | 15.08.2020 1:46:10 |
+----------+---------+--------------------+

Since the device1 starts failing from 15.08.2020 1:44:30, I don't want its record that goes after that timestamp.

The same for the device2.

So as a final result I want to have only data of all devices until they get first FAIL status:

+----------+-------------+--------------------+
| DeviceId | Temperature | TimeStamp          |
+----------+-------------+--------------------+
| 1        | 31          | 15.08.2020 1:42:00 |
| 2        | 40          | 15.08.2020 1:43:00 |
| 1        | 32          | 15.08.2020 1:44:00 |
+----------+-------------+--------------------+

I tried something like this

var query = _context
            .History
            .Include(h => h.Device)
            .AsNoTracking()
            .Where(h => h.DeviceTimeStamp <= h.Device.DeviceStatusHistory.FirstOrDefault(st => st.Status == 0).TimeStamp);

The problems is if a device never fails, I don't get its history at all.

like image 599
amplifier Avatar asked Aug 23 '26 04:08

amplifier


2 Answers

Basically you need "not exists" condition, i.e. get all History records for which does not exist DeviceStatusHistory record with the same DeviceId, Status == 0 and greater Timestamp.

Which with navigation properties in LINQ is expressed with !Any(...) condition rather than FirstOrDefault():

.Where(h => !h.Device.DeviceStatusHistory.Any(st =>
    st.Status == 0 && st.TimeStamp > h.DeviceTimeStamp));
like image 142
Ivan Stoev Avatar answered Aug 25 '26 23:08

Ivan Stoev


I have some untested code, can you try it. I think the logic should work for you.

var query = _context
            .History
            .Include(h => h.Device)
            .AsNoTracking()
            .Where(
h => h.DeviceTimeStamp <= h.Device.DeviceStatusHistory.FirstOrDefault(st => st.Status == 0)?.TimeStamp ?? DateTime.MaxValue);
like image 45
Andy Song Avatar answered Aug 25 '26 23:08

Andy Song



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!