Avatar billede gigi1 Nybegynder
26. februar 2013 - 16:52 Der er 23 kommentarer

Problemer med LEFT JOIN

Hey

Hvordan laver jeg en select sætning som udskriver således:

Depositum1 - Antal som har betalt dette depositum
Depositum2 - Antal som har betalt dette depositum
Depositum3 - Antal som har betalt dette depositum

Den skal alstå derfor uderskrive alle de despositummer som findes en gang og ved siden af skrive hvor mange som har betalt dette.

Jeg har data fordelt i to tabeller:

Tabel1: Udlån
Felt(er): DepositId
Beskrivelse: DepositId angiver hvilket depositum som er blevet bestalt.

Tabel2: Depositummer
Felt(er): Id, Amount
Beskrivelse: Amount angiver depositummet i kroner.
Avatar billede Syska Mester
26. februar 2013 - 17:12 #1
SELECT U.DepositId, COUNT(*) AS Antal FROM U.Udlån
INNER JOIN Depositummer D ON U.DepositId = D.DepositId
GROUP BY U.DepositId

Antager du har et ID som kæder de 2 sammen(Jeg har kaldt det DepositId) ellers er det ikke nemt at se hvor mange der har betalt.

Sig til hvis der skulle være noget jeg har misforstået.
Avatar billede Syska Mester
26. februar 2013 - 17:14 #2
Arghh.

SELECT U.DepositId, COUNT(*) AS Antal FROM Udlån AS U
INNER JOIN Depositummer D ON U.DepositId = D.DepositId
GROUP BY U.DepositId

Skulle have været "Udlån AS U". Håber det giver mening.

LEFT bruger du kun hvis du vil have noget med ud som ikke findes i den anden tabel, og det lader det ikke til at være hvad du vil her.
Avatar billede erikjacobsen Ekspert
26. februar 2013 - 17:16 #3
#1: med dette får du ikke depositid-er, hvor der ikke er nogle udlån knyttet til.

Noget i retning af:

SELECT D.Id, COUNT(U.DepositID) AS Antal FROM Depositnummer D
LEFT JOIN Udlån U ON D.Id = U.DepositId
GROUP BY D.Id
Avatar billede Syska Mester
26. februar 2013 - 17:26 #4
#erikjacobsen

Dohhh, korrekt. Note to self: Husk at slappe af når man kommer hjem fra arbejde.

Men håber da der er et unikt id for et deposit ... og der ikke kun er Id og Amount ... Ja, de to kunne godt være unikke sammen, men mon ikke også der er et UserId ... så kan man godt undvære en identity column.

( Og hvis jeg har skrevet noget vrøvl nu igen, så giver jeg mig selv skylden og kommer nok med endnu en Dohhh" )

:-P
Avatar billede gigi1 Nybegynder
26. februar 2013 - 17:35 #5
#3

Når jeg bruger din kode ser det ud som det skal.
Men jeg ville gerne have Amount i første kolonne og ikke Id'erne fra depositnummer.

SELECT D.Id, COUNT(U.DepositID) AS Antal FROM Depositnummer D
LEFT JOIN Udlån U ON D.Id = U.DepositId
GROUP BY D.Id

Sådn her: SELECT D.Amount, COUNT(U.DepositID) AS Antal FROM Depositnummer D

Men så får jeg følegende fejl:
Column 'D.Amount' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Avatar billede Syska Mester
26. februar 2013 - 18:23 #6
Hvis Amount ikke er det sammme, så kan du ikke. Hvis, så kan du lave en GROUP BY på den colomn også, men det giver ikke rigtig nogen mening, da "Amount" allerede burde være i din Udlån.

Du kan lave en SUM(column) så vil du få summen.

Du må forklare hvad du vil, så kan det sikkert lade sig gøre. Det virker dog mere som om du vil have dem enlektvis og derfor hører det ikke til i databasen, da det så mere er Business Logic.
Avatar billede gigi1 Nybegynder
26. februar 2013 - 18:30 #7
Okay.

Lad os sige at jeg vil have følgende slut resultat:

----------------------
Beløb  - Antal betalinger
100 kr - 10
200 kr - 20
300 kr - 30
----------------

Tabel 1
Id - Beløb
1  - 100 kr
2  - 200 kr
3  - 200 kr

Tabel 2
Id - DepositId (reference til Tabel 1 kolonne = Id)
1  - 1
2  - 2
3  - 3
Avatar billede gigi1 Nybegynder
26. februar 2013 - 18:33 #8
Kolonnen Id i tabel 2 behøves naturligvis ikke.
I tabellen er der naturligvis også en UserId kolonne som reference til en helt anden tabel.
Avatar billede erikjacobsen Ekspert
26. februar 2013 - 18:58 #9
Du kan (utestet)

SELECT MAX(D.amount), COUNT(U.DepositID) AS Antal FROM Depositnummer D
LEFT JOIN Udlån U ON D.Id = U.DepositId
GROUP BY D.Id
Avatar billede gigi1 Nybegynder
26. februar 2013 - 19:07 #10
#9

Nu virker det.

Det var smart med den MAX funktion.

Tak for hjælpen :-)
Avatar billede Syska Mester
27. februar 2013 - 18:08 #11
Hvis alle beløb burde samme det samme så ville jeg bruge group by og select den kolonne, så vil du automatisk finde fejl da du så får et forkert resultat ud.

Udover det så ville jeg nok flytte amount over i den anden table, da der jo ikke er noget der lige nu forhindre dig i at skrive forkerte ting ind i den deposit tabel.
Avatar billede erikjacobsen Ekspert
27. februar 2013 - 20:25 #12
Nu er det ikke til at vide, hvilken forretningsmodel, der ligger bag.

Men der er et problem, hvis prisen for et depositum kan ændre sig over tid. Hvis depositum af type 1 ændres fra 100 kr til 110 kr, vil det i den beskrevne model betyde, at kunder der betalte 100 kr nu vil få 110 kr tilbage i deres depositum.

Så enten skal de 100 kr stå i udlåns-tabellen direkte (som vel nok er en almindelig og god forretningsskik), eller også skal man sørge for at en depositumstype kan sættes inaktiv. Så vil man være nødt til at lave et depositum af type 4 til 110 kr.

Det er svært/umuligt at rådgive om hvad spørgerens model skal være, når vi ikke ved hvad han er ved at lave.
Avatar billede Syska Mester
27. februar 2013 - 20:41 #13
Svært ... måske, umligt nej ...

Jeg synes det lugter mere af der ikke er tænkt over tingene og det er jo ofte også derfor man kommer herind.

Man kunne også tage Max/Min ... hvis det bare er som information ark.

Lige meget hvad ... så vil jeg stadig fra råde at bruge "Min/Max".

Men du skal i hvert fald huske at tage højde for at MAX kan give null ... ISNULL(MAX(D.Amount), 0)

mvh
Avatar billede erikjacobsen Ekspert
27. februar 2013 - 20:47 #14
Hvis feltet amount er defineret som NOT NULL, så giver MAX i denne sammenhæng ikke NULL - men ellers kan den jo.
Avatar billede Syska Mester
27. februar 2013 - 21:16 #15
Men hvad så når der ikke er nogen rows i "deposit" table? Så ville jeg antage den bliver null ... og så er det jo summen af en "NULL" for den row.

Er den klog nok til at se på data typen for den row den ikke kunne joine på? og antage en default 0 eller hvad der nu er deffineret?

Jeg har ikke testet det, da jeg ikke er i nærheden af en SQL Server, men tvivler måske lidt ... ellers har jeg lært noget nyt i dag.
Avatar billede erikjacobsen Ekspert
27. februar 2013 - 21:30 #16
Det der står på venstresiden i den LEFT JOIN, i min udgave, #9, bestemmer hvilken rækker der kommer, uanset indhold af deposit-tabellen. Så det er ligegyldigt om der er nogle deposits eller ej ;)
Avatar billede Syska Mester
27. februar 2013 - 21:44 #17
Ja ... men du kommer vel stadig til at tage MAX(null) i de tilfælde hvor et Udlån endnu ikke har nogen deposits.

Det synes jeg ikke lige din forklaring tager højde for.

Du ville jo netop have den til left join så den kunne tælle 0 rows ... og der vil jeg jo mene D.Amount er null.
Avatar billede Syska Mester
27. februar 2013 - 21:47 #18
FUCKKKKKKKKKKKKKK,

Jeg har hele tiden læst det modsat ...
Avatar billede Syska Mester
27. februar 2013 - 21:49 #19
Hahha, glem det hele ... havde relationen modsat i min hjerne.

Men så er det jo endnu mere logisk bare at tage en GROUP BY på D.Amount ... i stedet for at tage Max, da det jo altid vil være det samme.
Avatar billede erikjacobsen Ekspert
27. februar 2013 - 22:22 #20
Velkommen i klubben :)  Hvis du antager at beløbene er forskellige, så kan man vel godt, men det er jo ikke så'n nødvendigvis på den måde....
Avatar billede Syska Mester
27. februar 2013 - 22:38 #21
#erikjacobsen

Der skal ikke være nogen tvivl her, jeg ville bruge GROUP BY. Jeg tror SQL serveren er bedre optimeret der. Den looper nok alligevel over duplicates rows og fjerner den når du kører din Argregate method.

Men nok i små tings afdelingen :-)
Avatar billede gigi1 Nybegynder
28. februar 2013 - 18:50 #22
#12 Jeg har lavet det sådan at hvis depositummet skal ændres ændre man dpositums id'et i udlånstabellen. Hvis det nye depositum ikke findes allerede oprettes der et nyt id i depositumstabellen.
Avatar billede erikjacobsen Ekspert
28. februar 2013 - 19:08 #23
Det er ikke så tosset ;)
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