[MySQL] subquery omzeilen

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hoi,

even op voorhand de situatie schetsen, ik heb 2 tabellen:

employees
employee_id
employee_numberofchilds (INT)
employee_age (INT)

employee_logins
employee_id
employee_logindate

Wat ik wil is een lijst van werknemers die in de employee_logins voorkomen, in de lijst tel ik het aantal werknemers met met 1,2 en 3 kinderen. Omdat de relatie tussen employees en employees_logins 1 of meer is, zie ik geen andere oplossing dan met een subquery te werken:

code:
1
2
3
4
5
 SELECT COUNT(CASE WHEN employee_numberofchilds = 1 THEN 1 ELSE null END) as tel_1,
COUNT(CASE WHEN employee_numberofchilds = 2 THEN 1 ELSE null END) as tel_2, 
COUNT(CASE WHEN employee_numberofchilds = 3 THEN 1 ELSE null END) as tel_3 
from employees 
where empoyee_id in (SELECT distinct employee_id from employee_logins)


Nu bevat de tabel employee_login enorm veel records, dus ik wil liefst geen subquery. Dit oplossen met een krijg ik ook niet voor elkaar. Bestaat er een betere manier om dit op te lossen?

Edit: Ik weet ook dat ik in dit voorbeeld het tellen kan oplossen met een GROUP BY of dergelijke, maar in mijn echte situatie heb ik een COUNT nodig.

[ Voor 6% gewijzigd door Verwijderd op 23-06-2009 12:58 ]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Verwijderd schreef op dinsdag 23 juni 2009 @ 12:56:
Nu bevat de tabel employee_login enorm veel records, dus ik wil liefst geen subquery. Dit oplossen met een krijg ik ook niet voor elkaar. Bestaat er een betere manier om dit op te lossen?
Hoezo wil je geen sub-query? Loop je tegen performance problemen aan? Als je indexen goed liggen hoeft het namenlijk niet perse een probleem te zijn.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

Verwijderd

SQL:
1
2
3
SELECT employee_numberofchilds, COUNT(employees.employee_id) AS count 
FROM employees JOIN employee_logins ON employees.employee_id = employee_logins.employee_id 
GROUP BY employee_numberofchilds

Zoiets?

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
COUNT(DISTINCT employee_id) ;) Anders ga je dubbel tellen.

{signature}


Acties:
  • 0 Henk 'm!

  • Miyamoto
  • Registratie: Februari 2009
  • Nu online
Voutloos schreef op dinsdag 23 juni 2009 @ 13:17:
COUNT(DISTINCT employee_id) ;) Anders ga je dubbel tellen.
De count gaat over de tabel employees. Hierin zijn de id's uniek (mag ik hopen :+)

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Miyamoto schreef op dinsdag 23 juni 2009 @ 13:39:
[...]

De count gaat over de tabel employees. Hierin zijn de id's uniek (mag ik hopen :+)
Aangezien hij gejoined is, zal hij niet uniek zijn in de resultset ;)

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Woy schreef op dinsdag 23 juni 2009 @ 13:45:
[...]

Aangezien hij gejoined is, zal hij niet uniek zijn in de resultset ;)
Klopt, dit geen nog altijd geen uniek resultaat

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Wat gaat dan goed met mijn suggestie? Geef eens een test set en leg duidelijker het gewenste resultaat uit?

{signature}


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
En dan nog, waarom wil je perse geen sub-query? Heb je met EXPLAIN gezien dat het performance problemen op gaat leveren?

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Woy schreef op dinsdag 23 juni 2009 @ 14:45:
En dan nog, waarom wil je perse geen sub-query? Heb je met EXPLAIN gezien dat het performance problemen op gaat leveren?
Omdat employee_logins miljoenen records bevat, waar helemaal doorgehobbeld moet worden. Beter om te joinen dus...

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Voutloos schreef op dinsdag 23 juni 2009 @ 14:43:
Wat gaat dan goed met mijn suggestie? Geef eens een test set en leg duidelijker het gewenste resultaat uit?
Ik moet met een case when werken, en daar kan ik de distinct niet gebruiken

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Verwijderd schreef op dinsdag 23 juni 2009 @ 14:51:
[...]

Ik moet met een case when werken, en daar kan ik de distinct niet gebruiken
Je moet niet met een case werken, je moet de reacties in je topic lezen. De opmerking van voutloos was een aanvulling op Boland. In hun (gecombineerde) voorstel zie ik nergens een case terug komen.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Janoz schreef op dinsdag 23 juni 2009 @ 14:56:
[...]

Je moet niet met een case werken, je moet de reacties in je topic lezen. De opmerking van voutloos was een aanvulling op Boland. In hun (gecombineerde) voorstel zie ik nergens een case terug komen.
Ga er nu ff vanuit dat ik met een case moet werken. In het geval van boland, krijg je niet enkel de count van 1,2 en 3 kinderen maar ook van de rest (4,5,...) en die wil ik niet in de lijst hebben

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:15

Janoz

Moderator Devschuur®

!litemod

Verwijderd schreef op dinsdag 23 juni 2009 @ 14:59:
[...]


Ga er nu ff vanuit dat ik met een case moet werken. In het geval van boland, krijg je niet enkel de count van 1,2 en 3 kinderen maar ook van de rest (4,5,...) en die wil ik niet in de lijst hebben
Dan voeg je toch een 'where minder dan 4 kinderen' toe?

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Als je dit vaak uit moet voeren dan zou ik in employees een veld hasLoggedIn maken, en dan een index toevoegen op (hasLoggedIn,employee_numberofchilds).

Daarna is het nog een SELECT employee_numberofchilds,count(*) FROM employees WHERE hasLoggedIn=1 GROUP BY employee_numberofchilds

Sneller krijg je het niet.

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Klopt op zich. Maar aangezien de ts de query nog niet wist, kan de uiteindelijke query onmogelijk al geprofied zijn, dus is ook niet zeker of het een probleem is. NA profilen zou hetgeen jij zegt een vd mogelijke trucs kunnen zijn.

{signature}


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Verwijderd schreef op dinsdag 23 juni 2009 @ 14:48:
[...]

Omdat employee_logins miljoenen records bevat, waar helemaal doorgehobbeld moet worden. Beter om te joinen dus...
Ja ik had gelezen dat er veel records zijn, maar ik zie nog geen reden waarom een join perse beter moet zijn dan een sub-query.

Kijk eerst eens met explain hoe de execution plan van de query is.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Profilen/explainen dus.

Overigens klopt het wel dat joins vaak sneller zijn omdat subqueries t/m 5.1 vaak onterecht als dependent subquery uitgevoerd worden. Maar goed, dat is 1 vd optimalisatietrucs: je zal eerst moeten meten en dan ook nog verifieren dat het voor een specifieke query ook boeit.

{signature}


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Voutloos schreef op dinsdag 23 juni 2009 @ 16:10:
Profilen/explainen dus.

Overigens klopt het wel dat joins vaak sneller zijn omdat subqueries t/m 5.1 vaak onterecht als dependent subquery uitgevoerd worden. Maar goed, dat is 1 vd optimalisatietrucs: je zal eerst moeten meten en dan ook nog verifieren dat het voor een specifieke query ook boeit.
Ik weet dat dat niet het sterkste punt van MySql is, maar je moet natuurlijk pas naar oplossingen gaan zoeken als je ( dmv profilen/eplainen ) erachter komt dat het een probleem is, niet omdat je denkt dat het een probleem is.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Dat zeg ik toch ook? 8)7

{signature}


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ik was jou ook niet aan het tegenspreken ;), ik wilde meer benadrukken, dat alhoewel het wel zo kan zijn, je toch eerst gaat kijken of het wel het geval is.

[ Voor 23% gewijzigd door Woy op 23-06-2009 16:25 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

Verwijderd

SQL:
1
2
3
4
SELECT employee_numberofchilds, COUNT(DISTINCT employees.employee_id) AS count 
FROM employees JOIN employee_logins ON employees.employee_id = employee_logins.employee_id 
WHERE employee_numberofchilds < 4 
GROUP BY employee_numberofchilds

Klaar.

Je gaat zoiets toch niet oplossen met 3 CASEs 8)7 Het gaat er toch om dat de query netjes is en dat is bovenstaande; al zeg ik het zelf.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Sowieso is het meervoud van child children, niet childs ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1