Ik was bezig aan iets in Django. Dat doet in principe allemaal mooie dingen op hoog niveau en een mens moet zijn poten niet vuilmaken aan de database, een groot gemak mijnheer mevrouw.

Maar op een bepaald punt loopt het in de soep met de snelheid en de efficiëntie, en op een bepaald moment lukt het gewoon niet om een view samen te stellen met combinaties van .filter() en .exclude() en subqueries in allerlei stappen en dan gedoe met {% for %}-dingen in elkaar genest en groupers en gedoe op een template-pagina: ja, het werkt min of meer wel, maar het is oérend traag. En véél te complex.

En dan geeft een mens het op, en wordt het gewoon

lijst = Dingen.objects.raw("""
  SELECT p.id, p.veld1, p.veld2, 
         r.veld1, r.veld2, a.veld2, c.veld1
  FROM tabel1 p 
       inner join tabel2 r on p.r_id=r.id
       inner join tabel3 b on p.id=b.p_id
       left outer join tabel4 a on p.id=a.p_id
       left outer join tabel5 c on p.id=c.p_id
  WHERE
       r.veld1< {0} and b.veld1 in ({1}) and
       p.veld3=0 and p.veld4=1 and
       (a.veld3=1 or a.id is null) and 
       (c.ctype='blah' or c.id is null) and 
       p.id not in (select p_id from tabel4
                    where veld1={0} or s_id=2)
  GROUP BY p.id
  ORDER BY r.veld1, r.veld2, p.veld2
  """.format(parameter1,parameter2))

Jaja, ’t is niet zoals het zou moeten zijn, maar het is maar voor een rapport dat zeer zeer zelden moet lopen, en doet zó een deugd om in de rapte wat SQL bij elkaar te schrijven en dat het allemaal wérkt.

Ik krijg er bijna heimwee naar echt programmeren en echt databasegedoe door.



Reacties

2 reacties op “Het moment dat een mens foert zegt”

  1. Ik vind SELECT’s met GROUP BY’s zonder aggregate of HAVING toch altijd wel iets raars / nasty.
    Ben je niet beter met een DISTINCT ?

    Ik veronderstel dat je een group by doet omdat je in dit geval per p.id slechts één row wilt hebben. Echter, welk record gaat de database dan kiezen ? Of hoe moet de DB dan bepalen van welk record hij veld1, veld2, etc… moet kiezen ?

    Ik bedoel maar, je kan bv deze 2 records hebben die aan je where voldoen:

    1, veld1a, veld2a
    1, veld1b, veld2b

    Door die group by op id zal er van deze 2 records slechts één record geselecteerd worden. Maar welkeen ?

    1. Dit is maar een stukje van de query. 🙂

      Het gaat om mensen met eventueel contactmogelijkheden en eventueel adressen, en als ze een adres hebben, dan wil ik het laatst geldige adres.

      En dat meest recente doe ik in die tweede outer join, met een subsubquery —

      left outer join
      (select a1.adres, a1.persoon_id, a1.geldig, a1.van, a1.tot
      from adres a1
      inner join (
      select persoon_id, max(van) as recentsteongeldig
      from adres
      where geldig=0
      group by persoon_id
      ) a2 on a1.persoon_id=a2.persoon_id and
      a1.van = recentsteongeldig
      ) a on p.id=a.persoon_id

      …maar dat zijn dus typisch van die toestanden die groeien en groeien, en die eigenlijk geen goed idee zijn, maar als het maar voor eventjes is… ah well. 🙂