Home > Software design >  NULL, then any other value in GROUP BY
NULL, then any other value in GROUP BY

Time:04-09

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.

CodePudding user response:

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

  • Related