[MySQL] COUNT op rij uit JOIN geeft geen resultaat

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb een relatief simpele MySQL query, maar krijg niet de verwachte resultaten terug.

De query moet berichten (DM's) ophalen uit de database inclusief het aantal bijlagen dat erbij hoort.

Hier een (gestript) voorbeeld van de query:
SQL:
1
2
3
4
5
6
7
8
9
10
11
    SELECT
        `b`.`id`,
        `b`.`titel`,
        `b`.`onderwerp`,
        COUNT(`bb`.`bijlage_id`) as `bijlagen`
    FROM
        `berichten` as `b`
    LEFT JOIN
        `bericht_bijlagen` as `bb`
    ON
        `bb`.`bericht_id` = `b`.`id`


Dit werkt perfect, maar alleen als er ook daadwerkelijk bijlagen zijn. Wanneer er geen bijlagen zijn voor het bericht, dan wordt deze niet getoond in de resultaten. Om dezelfde reden wordt het met een JOIN gedaan, zodat bijlagen niet verplicht zijn.

Het blijkt dat de JOIN de waarde NULL teruggeeft, waardoor de COUNT niets doet en dus geen resultaat kan vinden. Dit heb ik proberen op te lossen met NULLIF():
SQL:
1
COUNT(NULLIF(`bb`.`bijlage_id`,0)) as `bijlagen`

maar helaas werkt dit ook niet, omdat MySQL waarschijnlijk vindt dat de hele tabel niet bestaat.

Nu kan ik natuurlijk met meerdere queries werken, of met interne SELECT's, maar volgens mij moet mijn idee wel mogelijk zijn.
Is er iemand die hier een oplossing voor heeft, of moet ik gewoon "smerig" meerdere queries draaien om het verwachte resultaat te krijgen?

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
SQL:
1
Coalesce(COUNT(`bb`.`bijlage_id`),0)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

Verwijderd

Mis je niet ergens een GROUP BY?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
RobIII schreef op woensdag 29 juni 2011 @ 14:07:
SQL:
1
Coalesce(COUNT(`bb`.`bijlage_id`),0)
Ik krijg hiermee hetzelfde resultaat als mijn voorbeeld query (of met NULLIF, welke in dit geval exact hetzelfde doet).
Verwijderd schreef op woensdag 29 juni 2011 @ 14:40:
Mis je niet ergens een GROUP BY?
Had ik dan niet meerdere keren dezelfde row moeten krijgen wanneer ik een GROUP BY mis? Ik krijg nu helemaal geen rijen terug wanneer er geen bijlagen zijn. Een GROUP BY is juist nodig wanneer je teveel rijen terug krijgt ;)


Het lijkt erop dat de COUNT functie niet om kan gaan met de waarde NULL, want een JOIN geeft NULL terug wanneer er geen resultaat is. Er wordt nu dus COUNT( NULL ) gedaan, wat technisch niet kan.
De reden waarom NULLIF en COALESCE in dit geval geen uitkomst bieden is mij overigens een raadsel.

Het feit dat er geen foutmelding wordt gegeven kan ik me voorstellen, maar dat er dan maar helemaal niets wordt gedaan vind ik wel vreemd.


P.S. dit probleem is niet van levensbelang en meer een observatie die vraagtekens bij mij oproept. Ik heb dus al een query die werkt (ipv count een subquery), maar gezien de technische "fout" (IMHO) wel een interessant punt om over door te denken.

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Verwijderd schreef op woensdag 29 juni 2011 @ 14:40:
Mis je niet ergens een GROUP BY?
Dat sowieso inderdaad; helemaal gemist :D
Hoe werkt dat GROUP BY nu eigenlijk?

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ok, ik heb nu de volgende query en het lijkt te werken :o
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
    SELECT 
        `b`.`id`, 
        `b`.`titel`, 
        `b`.`onderwerp`, 
        COUNT(`bb`.`bijlage_id`) as `bijlagen` 
    FROM 
        `berichten` as `b` 
    LEFT JOIN 
        `bericht_bijlagen` as `bb` 
    ON 
        `bb`.`bericht_id` = `b`.`id`
    GROUP BY
        `bb`.`bericht_id`

(inderdaad, een GROUP BY)

Hoewel MySQL een GROUP BY niet verplicht (is een brakke database ;)) vind ik het vreemd dat het resultaat zo vreemd is. Ik verwacht nu dat alle bijlagen behorend tot een bericht gegroepeerd worden en een COUNT dus altijd op 1 komt. zelf verkeerd gelezen...
welkom in de wondere wereld van SQL

Acties:
  • 0 Henk 'm!

  • LazySod
  • Registratie: Augustus 2003
  • Laatst online: 11:38

LazySod

Scumbag with a mission

Verwijderd schreef op woensdag 29 juni 2011 @ 15:18:
Ok, ik heb nu de volgende query en het lijkt te werken :o
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
    SELECT 
        `b`.`id`, 
        `b`.`titel`, 
        `b`.`onderwerp`, 
        COUNT(`bb`.`bijlage_id`) as `bijlagen` 
    FROM 
        `berichten` as `b` 
    LEFT JOIN 
        `bericht_bijlagen` as `bb` 
    ON 
        `bb`.`bericht_id` = `b`.`id`
    GROUP BY
        `bb`.`bericht_id`

(inderdaad, een GROUP BY)

Hoewel MySQL een GROUP BY niet verplicht (is een brakke database ;)) vind ik het vreemd dat het resultaat zo vreemd is. Ik verwacht nu dat alle bijlagen behorend tot een bericht gegroepeerd worden en een COUNT dus altijd op 1 komt. zelf verkeerd gelezen...


[...]
toon volledige bericht
Die GROUP BY is inderdaad erg brak dan. Vervang hem door

SQL:
1
GROUP BY b.id, b.titel, b.onderwerp


en dan werkt het op andere databases ook

of alternatief, aangezien b.id waarschijnlijk uniek is:

SQL:
1
2
3
4
5
6
7
8
select b.id,
         max(b.titel),
         max(b.onderwerp),
         count(bb.bijlage_id) 

... 

group by b.id

Proof is the idol before whom the pure mathematician tortures himself. (Sir Arthur Eddington)


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
LazySod schreef op woensdag 29 juni 2011 @ 15:25:
[...]
of alternatief, aangezien b.id waarschijnlijk uniek is:

SQL:
1
2
3
4
5
6
select b.id,
         max(b.titel),
         max(b.onderwerp),
         count(bb.bijlage_id) 
... 
group by b.id
Hmm, wat betekent een max op een textveld dan? Persoonlijk zou ik liever voor de group by op id,titel,onderwerp gaan. Als dan later ooit (vanwege reden x/y/z) titel/onderwerp/id niet meer uniek is dan krijg je voorspelbaar gedrag (meerdere regels) ipv dat je bij toeval gewoon 1 regel terugkrijgt die voldoet aan max voor textvelden maar die niet is wat je zocht ( veel plezier met debuggen )

Acties:
  • 0 Henk 'm!

  • LazySod
  • Registratie: Augustus 2003
  • Laatst online: 11:38

LazySod

Scumbag with a mission

Die max betekent in dit geval niets - omdat er maar 1 record is (aangezien het ID veld al uniek is). Als ID niet meer uniek is dan is de max de hoogste string value (en die is, in Oracle in ieder geval, afhankelijk van NLS settings).

De group by over meerdere kolommen geniet daarom ook mijn voorkeur, maar je moet een manier kiezen om van de "not a group by expression" error af te komen en het gebruik van max (en min) kunnen daar helpen.

[ Voor 16% gewijzigd door LazySod op 29-06-2011 21:15 ]

Proof is the idol before whom the pure mathematician tortures himself. (Sir Arthur Eddington)


Acties:
  • 0 Henk 'm!

  • ZaZ
  • Registratie: Oktober 2002
  • Laatst online: 21-07 23:29

ZaZ

Tweakers abonnee

Start je sessie met ONLY_FULL_GROUP_BY, of nog beter, stel het in op je server.
Dat voorkomt dit soort fouten

Lekker op de bank

Pagina: 1