'NULL, then any other value in GROUP BY
MySQL 5.7. Given a table of vehicles, and a table of alerts, with a 1:N relationship. A vehicle could have no alerts, or multiple alerts in a mixture of closed and open states. If alert.closed_time is NULL, the alert is considered 'OPEN'.
To collapse all alerts to a single status value for each vehicle prioritising 'OPEN' alerts, I have been doing the following:
SELECT
CASE
WHEN SUM(CASE WHEN a.closed_time IS NULL THEN 1 ELSE 0) END) > 0 THEN 'OPEN'
ELSE 'CLOSED'
END AS a.status,
v.id
FROM alerts a JOIN vehicles v ON a.vehicle_id = v.id
GROUP BY v.id;
Which seems to be working OK. However, it strikes me there ought to be a simpler/more efficient way than nested CASE statements! It's important that if there is any NULL value in the column, I prioritise it over any timestamps. I did wonder about something like:
GROUP_CONCAT(COALESCE(a.closed_time, 'ACTIVE'))
and then looking for strings containing 'ACTIVE' in the column, but I'm not sure that's any better.
Solution 1:[1]
Given that you ultimately need to translate a datetime value into a string, I don't think it's possible with a single function call. However, you could simplify things a bit by using a conditional MAX() to return 1 if there are any open alerts, otherwise 0. Then use IF() to translate the boolean result into the statuses: "OPEN" or "CLOSED"
SELECT
IF(MAX(a.closedTime IS NULL) = 1, 'OPEN', 'CLOSED') AS status
, v.id
FROM alerts a JOIN vehicles v ON a.vehicle_id = v.id
GROUP BY v.id
ORDER BY v.id
Results:
| status | id |
|---|---|
| OPEN | 1 |
| CLOSED | 2 |
| OPEN | 3 |
db<>fiddle here
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
