Avatar billede _cyberdude_ Nybegynder
14. februar 2007 - 17:52 Der er 12 kommentarer og
1 løsning

Hjælp til en SQL sætning

Ved ikke lige om jeg skal stille spørgsmålet her, eller under andre Database kategorier. Men stiller det her, så må i lige fortælle mig om jeg skal flytte den :P..

Jeg har lige et lille problem med en SQL sætning, ved ikke helt om jeg kan gøre det sådan eller om jeg skal gøre noget helt andet, ville være bedst at det bliver i en og samme sætning..

Jeg har en tabel med 4 felter, navn, id, level, size, bonus
I tabel er der en masse rows. En row består altså af at et navn, et id, et level nummer, og et størrelse nummer, og bonus som er en boolean (true/false).

Et eksempel ville være:

(navn, id, level, size, bonus)
etnavn1, 12, 1, 197,false
etnavn1, 12, 2, 201,true
etnavn1, 12, 3, 245,true
etnavn1, 12, 4, 290,false
etnavn1, 33, 1, 112,true
etnavn1, 33, 2, 179,true
etnavn1, 33, 3, 201,false
etnavn1, 33, 4, 210,false
etnavn2, 15, 1, 197,true
etnavn2, 15, 2, 201,true
etnavn2, 15, 3, 245,true
etnavn2, 15, 4, 290,true
etnavn2, 102, 1, 112,false
etnavn2, 102, 2, 179,false
etnavn2, 102, 3, 201,false
etnavn2, 102, 4, 210,false

hvis dette giver mening? :)

Det jeg så skal bruge er at finde size af den højeste level som har bonus til en valgt værdi..

SELECT navn, id, MAX(level) AS [MaxLvl]
FROM [Tabel1]
WHERE Bonus=True AND navn='etnavn1'
GROUP BY navn, id;

Denne giver næsten det rigtige result altså den retunere navn, id og den højste level hvor bonus er true.
Jeg vil gerne have size med i denne, noget i retning af:

SELECT navn, id, size, MAX(level) AS [MaxLvl]
FROM [Tabel1]
WHERE Bonus=True AND navn='etnavn1'
GROUP BY navn, id, size;

men denne retunerer en samblanding af alle de resultater jeg fik før, med alle de forskellige levels der er for hver navn, id. Altså som om at Max(level) bliver taget for hver række.

Havde så også tænkt noget i retning af dette:

SELECT navn, id, size, level, MAX(level) AS [MaxLvl]
FROM [Tabel1]
WHERE Bonus=True AND navn='etnavn1' AND Maxlvl = level
GROUP BY navn, id, size;

Men dette virker selvfølgeligt heller ikke, da Max(level) stadig bliver taget for hver unik række, som det jo givetvis er da jeg inkludere level med i select statementen.
Men hvad kan jeg så gøre? Skal jeg virkeligt dele den op i to select statements:

SELECT navn, id, MAX(level) AS [MaxLvl]
FROM [Tabel1]
WHERE Bonus=True AND navn='etnavn1'
GROUP BY navn, id;

og så bruge den MaxLvl der bliver retuneret, og indsætte den i:

SELECT navn, id, level, size
FROM [Tabel1]
WHERE Bonus=True AND navn='etnavn1' And level = [den tidligere maxlvl]
GROUP BY navn, id, level;

Hjælp! :D. Vil meget gerne have det hele i en statement.

Ekstra Info:
Databasen er i Access 2003
Bruger DAO til at kommunikere med databasen i Visual Basic 6.0.
Avatar billede terry Ekspert
14. februar 2007 - 19:30 #1
Your in the right category if its an Access dB your workig with.

I'll have a play around and see if I can come up with something.
Avatar billede terry Ekspert
14. februar 2007 - 19:39 #2
Can you give an example of what you want to see in the result?
Avatar billede _cyberdude_ Nybegynder
14. februar 2007 - 22:38 #3
Hmm..
If we take the example from before:

etnavn1, 12, 1, 197,false
etnavn1, 12, 2, 201,true
etnavn1, 12, 3, 245,true
etnavn1, 12, 4, 290,false
etnavn1, 33, 1, 112,true
etnavn1, 33, 2, 179,true
etnavn1, 33, 3, 201,false
etnavn1, 33, 4, 210,false
etnavn2, 15, 1, 197,true
etnavn2, 15, 2, 201,true
etnavn2, 15, 3, 245,true
etnavn2, 15, 4, 290,true
etnavn2, 102, 1, 112,false
etnavn2, 102, 2, 179,false
etnavn2, 102, 3, 201,false
etnavn2, 102, 4, 210,false

Then using the SQL statement I'm looking for:
Setting Bonus=True and navn = 'etnavn1'
I would want to return this those NOT in bracets ():

(etnavn1, 12, 1, 197,false)
(etnavn1, 12, 2, 201,true)
etnavn1, 12, 3, 245,true
(etnavn1, 12, 4, 290,false)
(etnavn1, 33, 1, 112,true)
etnavn1, 33, 2, 179,true
(etnavn1, 33, 3, 201,false)
(etnavn1, 33, 4, 210,false)
(etnavn2, 15, 1, 197,true)
(etnavn2, 15, 2, 201,true)
(etnavn2, 15, 3, 245,true)
(etnavn2, 15, 4, 290,true)
(etnavn2, 102, 1, 112,false)
(etnavn2, 102, 2, 179,false)
(etnavn2, 102, 3, 201,false)
(etnavn2, 102, 4, 210,false)

if navn is set to 'etnavn2' instead I would want to return this those NOT in bracets ():

(etnavn1, 12, 1, 197,false)
(etnavn1, 12, 2, 201,true)
(etnavn1, 12, 3, 245,true)
(etnavn1, 12, 4, 290,false)
(etnavn1, 33, 1, 112,true)
(etnavn1, 33, 2, 179,true)
(etnavn1, 33, 3, 201,false)
(etnavn1, 33, 4, 210,false)
(etnavn2, 15, 1, 197,true)
(etnavn2, 15, 2, 201,true)
(etnavn2, 15, 3, 245,true)
etnavn2, 15, 4, 290,true
(etnavn2, 102, 1, 112,false)
(etnavn2, 102, 2, 179,false)
(etnavn2, 102, 3, 201,false)
(etnavn2, 102, 4, 210,false)

So the things is, that using this SQL:

SELECT navn, id, MAX(level) AS [MaxLvl]
FROM [Tabel1]
WHERE Bonus=True AND navn='etnavn1'
GROUP BY navn, id;

almost gives me the correct result, though I don't get the specific size for the returned row. Therefor what I'm essentially trying to do is to add the Size to this SQL statement, so it also returns the size for each row that fullfills the WHERE statement.

Hope this gives sence.
Kan godt give den på dansk hvis nogen mente det kunne hjælpe? :)

Thanks for the help so far Terry :)
Avatar billede _cyberdude_ Nybegynder
14. februar 2007 - 22:38 #4
Edit: Brackets*
Avatar billede jba1548 Nybegynder
15. februar 2007 - 09:34 #5
Du kunne prøve at sætte distinct foran navn, altså

SELECT distinct(navn), id osv.

hvis det du vil have altså er navn 1 gang.
Avatar billede terry Ekspert
15. februar 2007 - 12:12 #6
I think I know what your after, will take a look later, rather busy right now.
Avatar billede terry Ekspert
15. februar 2007 - 18:10 #7
Doesn this give you what you want?

SELECT TOP 1 Tabel1.navn, Tabel1.ID, Tabel1.level, Tabel1.size
FROM Tabel1
WHERE (((Tabel1.navn)='etnavn1') AND ((Tabel1.bonus)=True))
ORDER BY Tabel1.level DESC;
Avatar billede _cyberdude_ Nybegynder
20. februar 2007 - 17:06 #8
Sorry, var 300 km væk hjemmefra et par dage..

jba:
Distinct hjalp ikke så meget, den gjorde ikke så meget forskel, desværre :(..

Terry:
Thanks, it is getting closer, but not quite it.. ;)
I think I didn't explain it thougroughly in the OP...

What your code gives me is almos correct, though the case is that each of the ID's can have different level, so ID 1 can maybe have level 1,2,3,4 and ID 2 might only have level 1,2,3... If this is the case your code only returns those that has level 1,2,3,4 and not the Size and ID of the one that only has 1,2,3...
Your code works in this case:

etnavn1, 12, 1, 197,false
etnavn1, 12, 2, 201,false
etnavn1, 12, 3, 245,false
etnavn1, 12, 4, 301,false
etnavn1, 12, 5, 302,true
etnavn1, 12, 6, 310,true
etnavn1, 33, 1, 112,false
etnavn1, 33, 2, 179,false
etnavn1, 33, 3, 201,false
etnavn1, 33, 4, 210,false
etnavn1, 33, 5, 221,true
etnavn1, 33, 6, 230,true

in this case your code will return, if bonus is set to false:
etnavn1, 12, 4, 301,false
etnavn1, 33, 4, 210,false

but in this case, notice that "etnavn1, 12, 4, 301,false" have just been removed:
etnavn1, 12, 1, 197,false
etnavn1, 12, 2, 201,false
etnavn1, 12, 3, 245,false
etnavn1, 12, 5, 302,true
etnavn1, 12, 6, 310,true
etnavn1, 33, 1, 112,false
etnavn1, 33, 2, 179,false
etnavn1, 33, 3, 201,false
etnavn1, 33, 4, 210,false
etnavn1, 33, 5, 221,true
etnavn1, 33, 6, 230,true

the returned rows will only be:
etnavn1, 33, 4, 210,false


but what i want in this case is that it returns:
etnavn1, 12, 3, 245,false
etnavn1, 33, 4, 210,false


I hope this makes it a bit more clear? :)..

What I am doing right now is that I execute two statements:

SELECT navn, id, MAX(level) AS [MaxLvl]
FROM [Tabel1]
WHERE Bonus=True AND navn='etnavn1'
GROUP BY navn, id;

Then I run through all results and take the MaxLvl value, and ID
And then execute this statement those using those values as varMaxLvl and varID:

SELECT size
FROM [Tabel1]
WHERE navn='etnavn1' And level = varMaxLvl AND ID = varID

Then get the fetch the result of Size, and run the through the next result from the former statement, this means I run a Statement for each row returned in the first Statement, and this gives me the result needed, but takes to much on a large number of records. So I would like to do this in one statement, really combining those two statements into one.

Thanks for the help so far..
Avatar billede terry Ekspert
20. februar 2007 - 19:30 #9
This is a simple solution which I hope you can use.

Make a query and name it qryMaxLevel
SELECT Tabel1.navn, Tabel1.ID, Max(Tabel1.level) AS MaxOflevel
FROM Tabel1
GROUP BY Tabel1.navn, Tabel1.ID, Tabel1.bonus
HAVING (((Tabel1.navn)='etnavn1') AND ((Tabel1.bonus)=False));

Now make another query and call it qryMaxLevelAndSize
SELECT qryMaxLevel.*, tabel1.size
FROM qryMaxLevel INNER JOIN tabel1 ON (qryMaxLevel.MaxOflevel = tabel1.level) AND (qryMaxLevel.ID = tabel1.ID) AND (qryMaxLevel.navn = tabel1.navn);
Avatar billede terry Ekspert
08. marts 2007 - 19:48 #10
hows it going cyberdude?
Avatar billede terry Ekspert
14. marts 2007 - 16:32 #11
are we getting there?
Avatar billede _cyberdude_ Nybegynder
12. september 2009 - 12:11 #12
Hey Terry, just saw this was still lying around... Long time ago.
I will close the subject, and I never really used this solution, I later changed the entire application... But write an answer and I'll give you the points, or else I'll close it in 2 days and give the points to jba. You don't seem to lack the points ;).. But thanks for your time 2 years ago.. Hehe...
Avatar billede terry Ekspert
12. september 2009 - 13:22 #13
Well I havent missed the points over the last couple of years so I think I'll survive without them :o)

Thanks for the offer but you can give them to jba as you suggested.

BR
Terry
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
Dyk ned i databasernes verden på et af vores praksisnære Access-kurser

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