I'm not sure I understand exactly what's in your table; there are no
integrity constraints, so it's hard to infer anything. I added a row
to cover a case you didn't mention; maybe you think it can never
happen, but there's nothing in your schema that prevents it.

select * from history order by license, date desc, controlcode desc;
==>
License     ControlCode  Date      
----------  -----------  ----------
Lic1        CC4          2004-01-03
Lic1        CC2          2004-01-03
Lic1        CC1          2004-01-01
Lic2        CC3          2004-02-02
Lic2        CC3          2004-02-01

> Any hints for making it at least as fast as Access?

You can't just add indices on every column. I think this does what you
want, and (to me) it's more readable:

select distinct license, controlcode, date from
  (select h.license lic, h.controlcode cc, h.date dt from
    (select license, max(date) d from history group by license) lmax,
    history h
   where h.license = lmax.license and h.date = lmax.d) lcmax,
  history
where license = lcmax.lic and date < lcmax.dt and
      (controlcode <> lcmax.cc or controlcode is null) ;
==>
License     ControlCode  Date      
----------  -----------  ----------
Lic1        CC1          2004-01-01

This doesn't tell you that Lic1 was activated twice on Jan 3; for that
you need a separate query:

select license, controlcode, date from
  (select h.license lic, h.date dt from
    (select license, max(date) d from history group by license) lmax,
    history h
    where h.license = lmax.license and h.date = lmax.d
    group by lic, date
    having count(*) > 1) lmax2,
  history
where license = lmax2.lic and date = lmax2.dt ;
==>
License     ControlCode  Date      
----------  -----------  ----------
Lic1        CC2          2004-01-03
Lic1        CC4          2004-01-03

There's a good explanation of indices in the slide show from the PHP
conference (starting around slide 50); the link is on the main SQLite
web page. I think I'd start with one index on (license, date); delete
the others.

> While the query executes, the whole database is locked!

Yes, you really don't want somebody changing the database while you're
trying to read it. If you want to see the reason for this, do a Google
search on 'dirty read' (SQLite does not allow dirty reads). This point
is stated pretty clearly in Section 3 of www.sqlite.org/lockingv3.html.

Regards

Reply via email to