Avatar billede KKKnudsen Nybegynder
08. januar 2015 - 14:14 Der er 8 kommentarer og
1 løsning

Kan ikke tælle rigtigt med COALESCE og CASE

Hvad gør jeg forkert her? Jeg har en database med byrådsmedlemmer. En del har skiftet parti i løbet af valgperioden og jeg vil gerne have en liste, der viser, hvor mange mandater de enkelte partier har lige nu.

Jeg har bl.a. disse kolonner:
kb_valg13 = parti, som medlemmerne blev valgt for
kb_valg13hop = parti, som nogle medlemmer er skiftet til
kb_ud = dato for, hvornår nogle medlemmer er trådt ud af byrådet.

Alle medlemmer af lokale lister skal blot slås sammen til "lokallister".

Problemet er, at jeg ikke kan lave en query, som tæller rigtigt, når der er sket et skifte til/fra en lokalliste. Fx er der pt. i alt 25 løsgængere, men listen viser kun 23. Det passer med de to fra lokallister, som er blevet løsgængere. Jeg har eksperimenteret med at lade et byrådsmedlem skifte fra en lokalliste til Venstre, men dette fanges heller ikke af min query.

Nedenstående er min seneste udgave, men jeg har prøvet alle mulige kombinationsmuligheder. Jeg formoder selv, at det er min CASE, der skaber problemer ...

    SELECT
    CASE
        WHEN kb_valg13 LIKE '%lokal%' OR kb_valg13 LIKE 'Slesvigsk Parti' OR kb_valg13hop LIKE '%lokal%' OR kb_valg13hop LIKE 'Slesvigsk Parti'
            THEN '<em>lokallister</em>'
        WHEN kb_valg13hop LIKE 'UP'
            THEN '<em>løsgængere</em>'
        ELSE COALESCE(kb_valg13hop, kb_valg13)
    END as Parti, COUNT(COALESCE(kb_valg13hop, kb_valg13)) as Antal
FROM kb_medlemmer
        WHERE kb_ud IS NULL
GROUP BY Parti
ORDER BY Antal DESC

[...]
echo "<tr><td>".$row->Parti."</td><td>".$row->Antal."</td></tr>";


vh Kenneth
Avatar billede arne_v Ekspert
11. januar 2015 - 02:36 #1
Jeg tror at dit problem er at nogen matcher baade foerste og anden WHEN. Og kommer i foerste kategori selvom de nok skulle i anden kategori.

Enten skal den foerste WHEN laves om eller saa kan du proeve og bytte om paa de to WHEN'er.
Avatar billede KKKnudsen Nybegynder
11. januar 2015 - 20:15 #2
Hej Arne

Når jeg fifler med query'en kan jeg se, at du har delvist ret i din formodning.

- Query'en i #1 fanger ikke dem, der har skiftet fra en lokalliste til et andet parti - men kan godt tælle de, der er blevet løsgængere.

- At bytte rundt på de to WHEN giver næsten det samme: Men nu kan den heller ikke tælle dem fra lokallister, der er blevet løsgængere.

- At slette WHEN med UP=løsgænger giver det samme som #1 (UP/løsgænger behandles som et parti hvilket også er forventeligt).

- Hvis jeg sletter begge WHEN og laver en liste med alle partier (inkl. de 50 lokallister), så tæller den helt rigtigt.

Er der nogen idéer til, hvordan jeg ellers kan bygge en query, der både samler alle lokallisterne i én og laver noget a la COALESCE(kb_valg13hop, kb_valg13)?

vh Kenneth
Avatar billede arne_v Ekspert
12. januar 2015 - 03:31 #3
Jeg tror at vi skal dele det her op i flere mindre delopgaver.

Ja - det kan man godt i SQL.

Det vil tit vaere langsomt, men den her database er jo ikke saa stor og derfor gaar det sikkert.

Foerst checker vi at:

SELECT COALESCE(kb_valg13hop, kb_valg13) AS kb_idag
FROM kb_medlemmer
WHERE kb_ud IS NULL

returnerer det den skal.

Saa lave vi den lille konvertering af diverse ikke-landsdaekkende partier:

SELECT
    CASE
        WHEN kb_idag LIKE '%lokal%' OR kb_idag = 'Slesvigsk Parti'    THEN 'lokallister'
        WHEN kb_idag = 'UP' THEN 'løsgængere'
        ELSE kb_idag
    END as kb_idag_justeret
FROM
(
SELECT COALESCE(kb_valg13hop, kb_valg13) AS kb_idag
FROM kb_medlemmer
WHERE kb_ud IS NULL
) x

Og ser om det virker.

Og saa taeller vi:

SELECT kb_idag_justeret,COUNT(*) AS antal
FROM
(
SELECT
    CASE
        WHEN kb_idag LIKE '%lokal%' OR kb_idag = 'Slesvigsk Parti'    THEN 'lokallister'
        WHEN kb_idag = 'UP' THEN 'løsgængere'
        ELSE kb_idag
    END as kb_idag_justeret
FROM
(
SELECT COALESCE(kb_valg13hop, kb_valg13) AS kb_idag
FROM kb_medlemmer
WHERE kb_ud IS NULL
) x
) xx
GROUP BY kb_idag_justeret

og ser om det virker.

Det er utestet, men jeg tror paa ideen!
Avatar billede KKKnudsen Nybegynder
12. januar 2015 - 13:13 #4
Fantastisk, Arne! Det virker!

Mange lange tak, der er point, hvis du lægger et svar.


Tillægsspørgsmål: Hvor kan jeg lægge en kolonne ind, der tæller mandaterne fra de partier, de oprindeligt blev valgt for (kb_valg13 WHERE kb_valgt13 = 1)?

Jeg har forsøgt mig med subqueries og UNION, men der sker ingenting ... (måske fordi nogle byrådsmedlemmer er trådt ud og andre er kommet til?)
Avatar billede arne_v Ekspert
13. januar 2015 - 04:39 #5
svar
Avatar billede arne_v Ekspert
13. januar 2015 - 04:41 #6
Det er vel stort set samme query bare uden COALESCE.

Kan du bruge 2 queries eller kan du bruge dem efter hinanden eller skal det vaere som kolonner.
Avatar billede KKKnudsen Nybegynder
13. januar 2015 - 13:22 #7
Query'en kan jeg sagtens lave, den her virker:

SELECT
    CASE
        WHEN kb_valg13 LIKE '%lokal%' OR kb_valg13 LIKE 'Slesvigsk Parti'
            THEN 'lokallister'
        ELSE kb_valg13
    END AS Parti, COUNT(kb_valg13) AS KV13
FROM kb_medlemmer
        WHERE kb_valgt13 = 1
GROUP BY Parti
ORDER BY KV13 DESC


... men jeg gerne have de to resultater som før-og-nu kolonner i samme tabel. Som nævnt har jeg puslet med subquery og union, men kan ikke få det til at virke og har heller ikke kunnet finde det særligt godt beskrevet noget sted.

Men så vidt jeg kan læse mig til, kan det give problemer, hvis der ikke er det samme antal rækker i begge kolonner - og der er jo ingen UP/løsgængere i før-kolonnen.
Avatar billede arne_v Ekspert
14. januar 2015 - 04:29 #8
SELECT *
FROM (en query som returnerer parti og kb_dag) xxx
LEFT JOIN (en query som returnerer parti og kb_valg) yyy
ON xxx.parti = yyy.parti
Avatar billede KKKnudsen Nybegynder
17. januar 2015 - 21:36 #9
Hej Arne

Nu har jeg endelig haft lejlighed til at afprøve dit forslag - og det virker! (naturligvis)

Mange, mange tak!
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester