SQLite User Forum

Can you see what I do wrong?
Login

Can you see what I do wrong?

(1) By anonymous on 2021-03-15 00:46:50 [link] [source]

create table log(name,dt,time_in,time_out);

insert into log values('Noname','2021-03-15','00:12','00:24');

select name, dt, time_in, time_out
  from log
  where dt > '2021-03-13'
  group by dt,time_in
  having max(time_out);

The above SELECT returns nothing when I expect one row. If I comment out the HAVING clause it works.

(2.1) By Keith Medcalf (kmedcalf) on 2021-03-15 01:09:48 edited from 2.0 in reply to 1 [link] [source]

The expression following HAVING must evaluate to a number which is interpreted as a boolean (True or False -- False is zero or null, and True is non-zero).

The expression max(time_out) evaluates to '00:24' which, when converted to numeric, is zero or false.

sqlite> select cast('00:24' as numeric);
┌──────────────────────────┐
│ cast('00:24' as numeric) │
├──────────────────────────┤
│ 0                        │
└──────────────────────────┘
sqlite>

If I can divine your intention properly, what you probably mean is:

  select name, dt, time_in, max(time_out)
    from log
   where dt > '2021-03-13'
group by dt, time_in
;

(3) By anonymous on 2021-03-15 14:28:04 in reply to 2.1 [source]

OK, thanks.

But what if my SELECT did not include the column whose max() I wanted?

What if I needed to return only the name, dt, and time_in from the group row that has the maximum time_out value?

Is there some way for HAVING to match the row with the lexicographically higher string value without resorting to more complicated solutions using sub-queries?

(4) By anonymous on 2021-03-15 14:43:33 in reply to 3 [link] [source]

Never mind, I figured it out.

HAVING time_out = max(time_out)

(5) By Gunter Hick (gunter_hick) on 2021-03-15 14:58:18 in reply to 4 [link] [source]

Note that this works only for SQLite. And even then, if you have multiple entries with identical dt, time_in and time_out fields (with time_out == max(time_out) from the (dt, time_in) group), then SQLite may return any one of the name values.

See https://sqlite.org/quirks.html#aggregate_queries_can_contain_non_aggregate_result_columns_that_are_not_in_the_group_by_clause

(6) By Keith Medcalf (kmedcalf) on 2021-03-15 15:12:24 in reply to 3 [link] [source]

The standard way would be to select what you want. An example that should work in anything that understands generic SQL might be:

select (
        select name
          from log
         where dt == o.dt
           and time_in == o.time_in
           and max_out == o.max_out
       ) as name,
       dt,
       time_in
  from (
          select dt,
                 time_in,
                 max(time_out) as max_out
            from log
           where dt > '2021-03-13'
        group by dt, time_in
       ) as o
;