Avatar billede trine_h Nybegynder
06. september 2011 - 19:40 Der er 14 kommentarer

union spørgsmål

Jeg har 2 tabeller: spoergsmaal og spoergsmaalbruger

jeg bruger nedenstående forespørgsel til at få returneret alle de spørgsmål som brugeren har oprettet.

SELECT us.spoergsmaalid, us.spoergsmaal, usb.erAktiv, us.erGlobal FROM `spoergsmaal`as us left join spoergsmaalbruger as usb on (us.spoergsmaalid = usb.spoergsmaalid) where usb.brugerid = @brugerId

Problemet er så at jeg i denne spoergsmaal tabel har 10 spoergsmaal som er "globale". Det er så meningen at denne forespørgsel både skal hente de globalespørgsmål + de spørgsmål brugeren selv har opettet (alle fra samme tabel (De globale spørgsmål har erGlobal = 1, de andre har erGlobal = 0) Hvordan laver jeg en forespørgsel som både returnerer de globale spørgsmål + brugerens egne spørgsmål? Det skal være sådan at hvis brugeren har valgt at et af de globale spørgsmål skal bruges - så skal det spørgsmål ikke forekomme 2 gange. (når brugeren vælger at et spørgsmål skal vises bliver det oprettet som en post i spoergsmaalbruger.

Tabellerne ser således ud:
 
Spørgsmaal
--------------
spoergsmaalId    Spoergsmaal        erGlobal
1                Hvad er dit navn  1
2                Hvor bor du?      1
3                Hvad er din alder? 0

SpoergsmaalBruger
sbId        brugerId      spoergsmaalId    erAktiv
1          1              1                1
1          1              3                1

En forespørgsel på brugerId = 1 burde her returnere spoergsmaal 1,2,3 (1 skal kun returneres 1 gang fordi brugeren allerede har valgt det)
Avatar billede Slettet bruger
06. september 2011 - 20:16 #1
Jeg har ikke testet det, men måske noget i stil med (hvor jeg vælger alle de globale først, og derefter lægger evt. private til):

SELECT spoergsmaalId, spoergsmaal, 1 AS erAktiv, erGlobal
FROM spoergsmaal
WHERE erGlobal = 1
UNION ALL
SELECT us.spoergsmaalId, us.spoergsmaal, usb.erAktiv, us.erGlobal
FROM spoergsmaal AS us
INNER JOIN spoergsmaalbruger AS usb ON us.spoergsmaalid = usb.spoergsmaalid
WHERE usb.brugerid = @brugerId
AND us.erGlobal = 0
Avatar billede trine_h Nybegynder
06. september 2011 - 20:27 #2
Problemet er så at erAktiv altid sættes til 1 - så kan jeg ikke se hvilke brugeren har valgt eller fravalgt igen.
Avatar billede Slettet bruger
06. september 2011 - 20:30 #3
Så tager vi den med (med forbehold for slåfejl) :)

SELECT us.spoergsmaalId, us.spoergsmaal, ISNULL(usb.erAktiv, 0) AS erAktiv, us.erGlobal
FROM spoergsmaal us
LEFT OUTER JOIN spoergsmaalbruger AS usb ON us.spoergsmaalid = usb.spoergsmaalid
WHERE usb.brugerid = @brugerId
AND us.erGlobal = 1
UNION ALL
SELECT us.spoergsmaalId, us.spoergsmaal, usb.erAktiv, us.erGlobal
FROM spoergsmaal AS us
INNER JOIN spoergsmaalbruger AS usb ON us.spoergsmaalid = usb.spoergsmaalid
WHERE usb.brugerid = @brugerId
AND us.erGlobal = 0
Avatar billede Slettet bruger
06. september 2011 - 20:34 #4
Måske skal isnull erstattes med ifnull når det er mysql.
Avatar billede trine_h Nybegynder
06. september 2011 - 20:40 #5
med ifnull gav den ingen fejl - den returnerede dog heller ingen poster.
Avatar billede trine_h Nybegynder
06. september 2011 - 20:42 #6
Rettelse: Den returnerer de rigtige poster hvis brugerid'et har oprettet de spørgsmål. Hvis brugerid'et som benyttes ikke har nogen poster returnerer den ikke de globale 2
Avatar billede trine_h Nybegynder
06. september 2011 - 20:44 #7
Måske bør jeg placere de globale sp. i en tabel for sig? Er det her en dårlig tabel struktur?
Avatar billede Slettet bruger
06. september 2011 - 21:36 #8
Der er en lille fejl i mit første select med join. Prøv med:

SELECT us.spoergsmaalId, us.spoergsmaal, IFNULL(usb.erAktiv, 0) AS erAktiv, us.erGlobal
FROM spoergsmaal us
LEFT OUTER JOIN spoergsmaalbruger AS usb ON us.spoergsmaalid = usb.spoergsmaalid AND usb.brugerid = @brugerId
WHERE us.erGlobal = 1
UNION ALL
SELECT us.spoergsmaalId, us.spoergsmaal, usb.erAktiv, us.erGlobal
FROM spoergsmaal AS us
INNER JOIN spoergsmaalbruger AS usb ON us.spoergsmaalid = usb.spoergsmaalid
WHERE usb.brugerid = @brugerId
AND us.erGlobal = 0
Avatar billede Slettet bruger
06. september 2011 - 21:48 #9
Jeg tror ikke det er en dårlig ide med at separere de globale spørgsmål fra brugernes egne spørgsmål, men du får selvfølgelig nogle flere tabeller at skrue sammen på den rigtige måde.
Avatar billede Slettet bruger
06. september 2011 - 21:50 #10
Det er i øvrigt ligegyldigt om du bruger UNION eller UNION ALL i ovenstående sql query.
Avatar billede trine_h Nybegynder
06. september 2011 - 22:20 #11
SELECT usg.spoergsmaalid, usg.spoergsmaal, usbg.erValgt FROM spoergsmaalGlobal as usg left join spoergsmaalBG as usbg on (usg.spoergsmaalid = usbg.spoergsmaalid) where usbg.brugerid = @brugerId

Nu har jeg prøvet at dele de "globale" spørgsmål ud i en egen tabel. Jeg er så bare i tvivl igen om hvorledes jeg får vist de globale spørgsmål uanset om de er blevet valgt (findes i spoergsmalbg tabellen) eller ej - og at hvert spørgsmål kun vises 1 gang uanset om det er valgt eller ej.
Avatar billede Slettet bruger
06. september 2011 - 23:26 #12
Hvis dine tabeller ser sådan ud:

Tabel spoergsmaalGlobal med kolonnerne:
spoergsmaalId
spoergsmaal

Tabel spoergsmaalBG:
sbId
brugerId
erValgt
spoergsmaal
spoergsmaalId
(kun én af de sidste to kolonner har en værdi, enten referer den til et globalt spørgsmål, eller det er et brugerdefineret spørgsmål)

Så kan det gøres med (igen UNION):
SELECT usg.spoergsmaalId, IFNULL(usg.spoergsmaal,usbg.spoergsmaal), IFNULL(usbg.erValgt,0) AS erValgt
FROM spoergsmaalGlobal AS usg
LEFT OUTER JOIN spoergsmaalBG AS usbg ON usbg.spoergsmaalId = usg.spoergsmaalId
UNION
SELECT NULL AS spoergsmaalId, spoergsmaal, erValgt
FROM spoergsmaalBG
WHERE spoergsmaalId IS NULL
AND brugerId = @brugerId

Og så må du kombinere usg.spoergsmaalId med usbg.sbId hvis du vil have et unikt id (ovenfor viser den bare NULL for dem som ikke er globale).

Kunne bedre lide de første tabeller du startede med, hvis der kun skal bruges to tabeller.

Med de nye tabeller ville jeg oprette en 3. tabel, hvor du kan se hvilke af de globale spørgsmål en bruger har valgt (f.eks. brugerId, spoergsmaalId, erValgt), og hvis et globalt spoergsmaal ikke står i denne tabel med denne bruger, tolkes den som om den ikke er valgt.

Jeg har desværre ikke en smuk løsning på en kombination af globale og brugerdefinerede spørgsmål i databasen som jeg selv ville være tilfreds med. Så det afhænger af hvad du selv synes er nemmest at arbejde med.
Avatar billede trine_h Nybegynder
07. september 2011 - 09:02 #13
Fantastisk hjælp. Tak for det. Placerer du et svar?
Avatar billede Slettet bruger
07. september 2011 - 18:48 #14
Pointene beholder du selv, ellers 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
Kategori
Computerworld tilbyder specialiserede kurser i database-management

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