Avatar billede babyworm Nybegynder
18. september 2007 - 15:17 Der er 11 kommentarer

Problemer med en Group By sætning

Hej med jer,

Jeg har bygget en shop på MySQL og skal have den konverteret til MS SQL. Følgende SQL virker i MySQL men ikke i MSSQL..

SELECT COUNT(I.ID) AS Number,B.ID As BasketID, I.ID As ItemID, I.Name, B.Price, I.Weight, S.Rank As ShippingRank,
S.ID As ShippingID
FROM Baskets B
INNER JOIN ItemStock ISt ON ISt.ID=B.ItemStockID
INNER JOIN Items I ON I.ID=ISt.ItemID
LEFT JOIN ShippingMethods S ON S.ID=I.ShippingMethodID
WHERE B.StatusID=0
AND B.SessionID=1043053607
GROUP BY I.ID, B.Price

Der kommer følgende fejl:
Msg 8120, Level 16, State 1, Line 1
Column 'Baskets.ID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Nogen der ved hvordan jeg kan løse det?
Avatar billede a1a1 Novice
18. september 2007 - 15:19 #1
SELECT COUNT(I.ID) AS Number,B.ID As BasketID, I.ID As ItemID, I.Name, B.Price, I.Weight, S.Rank As ShippingRank,
S.ID As ShippingID
FROM Baskets B
INNER JOIN ItemStock ISt ON ISt.ID=B.ItemStockID
INNER JOIN Items I ON I.ID=ISt.ItemID
LEFT JOIN ShippingMethods S ON S.ID=I.ShippingMethodID
WHERE B.StatusID=0
AND B.SessionID=1043053607
GROUP BY I.ID, B.Price, BasketID
eller evt.
SELECT COUNT(I.ID) AS Number,B.ID As BasketID, I.ID As ItemID, I.Name, B.Price, I.Weight, S.Rank As ShippingRank,
S.ID As ShippingID
FROM Baskets B
INNER JOIN ItemStock ISt ON ISt.ID=B.ItemStockID
INNER JOIN Items I ON I.ID=ISt.ItemID
LEFT JOIN ShippingMethods S ON S.ID=I.ShippingMethodID
WHERE B.StatusID=0
AND B.SessionID=1043053607
GROUP BY I.ID, B.Price, b.ID
Avatar billede babyworm Nybegynder
18. september 2007 - 15:20 #2
Ved den sidste, kommer følgende fejl:
Msg 8120, Level 16, State 1, Line 1
Column 'Items.Name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Avatar billede pierrehusted Nybegynder
18. september 2007 - 15:21 #3
MS-SQL kræver at alle de felter der vælges/vises i SELECT skal medtages i GROUP BY.
Og ja, det er lidt irriterende når man konverterer systemer fra MySQL.
Avatar billede michael_stim Ekspert
18. september 2007 - 15:23 #4
I Oracle, MSSQL osv skal man have alle de kolonner med i GROUP'en som man skal have udskrevet. Det er bare MySQL der ser gennem fingrene med det.
Avatar billede babyworm Nybegynder
18. september 2007 - 15:23 #5
Men så når jeg tager alle felter med, så gør den ikke som jeg gerne vil have.. den skal jo gruppere resultaterne sammen hvor I.ID og B.Price er ens, og tælle antal grupperede..
Avatar billede michael_stim Ekspert
18. september 2007 - 15:23 #6
Så kom det i stereo ;o)
Avatar billede babyworm Nybegynder
18. september 2007 - 15:32 #7
Men så når jeg tager alle felter med, så gør den ikke som jeg gerne vil have.. den skal jo gruppere resultaterne sammen hvor I.ID og B.Price er ens, og tælle antal grupperede..
Avatar billede a1a1 Novice
18. september 2007 - 15:43 #8
SELECT COUNT(I.ID) AS Number,B.ID As BasketID, I.ID As ItemID, I.Name, B.Price, I.Weight, S.Rank As ShippingRank,
S.ID As ShippingID
FROM Baskets B
INNER JOIN ItemStock ISt ON ISt.ID=B.ItemStockID
INNER JOIN Items I ON I.ID=ISt.ItemID
LEFT JOIN ShippingMethods S ON S.ID=I.ShippingMethodID
WHERE B.StatusID=0
AND B.SessionID=1043053607
GROUP BY I.ID, B.Price, BasketID, I.ID As ItemID, I.Name, B.Price, I.Weight, S.Rank
må det vel så være ;o)
Avatar billede babyworm Nybegynder
18. september 2007 - 15:47 #9
Altså.. den her virker.. (ikke helt efter hensigten)

SELECT COUNT(I.ID) AS Number,B.ID As BasketID, I.ID As ItemID, I.Name, B.Price, I.Weight, S.Rank As ShippingRank,
S.ID As ShippingID
FROM Baskets B
INNER JOIN ItemStock ISt ON ISt.ID=B.ItemStockID
INNER JOIN Items I ON I.ID=ISt.ItemID
LEFT JOIN ShippingMethods S ON S.ID=I.ShippingMethodID
WHERE B.StatusID=0
AND B.SessionID=1043053607
GROUP BY I.ID, B.Price, B.ID, I.ID, I.Name, I.Weight, S.Rank, S.ID


Den returnerer:
Number    Basket    ItemID    Name                Price    Weight
1    2843    7    Sandisk MicroSD 2GB Transflash    144.00    500
1    2844    7    Sandisk MicroSD 2GB Transflash    144.00    500
1    2845    7    Sandisk MicroSD 2GB Transflash    144.00    500


Den skal retúrnere:
Number    Basket    ItemID    Name                Price    Weight
3    2843    7    Sandisk MicroSD 2GB Transflash    144.00    500

Altså gruppere resultatet efter Number og Price
Avatar billede kjulius Novice
18. september 2007 - 22:03 #10
Altså den skal returnere det mindste B.ID, hvis ellers prisen er ens?

Så kan du bare sætte MIN på B.ID feltet og fjerne det fra GROUP BY.


SELECT COUNT(I.ID) AS Number, MIN(B.ID) As BasketID, I.ID As ItemID, I.Name, B.Price, I.Weight, S.Rank As ShippingRank,
S.ID As ShippingID
FROM Baskets B
INNER JOIN ItemStock ISt ON ISt.ID=B.ItemStockID
INNER JOIN Items I ON I.ID=ISt.ItemID
LEFT JOIN ShippingMethods S ON S.ID=I.ShippingMethodID
WHERE B.StatusID=0
AND B.SessionID=1043053607
GROUP BY I.ID, B.Price, I.ID, I.Name, I.Weight, S.Rank, S.ID

Problemet opstår fordi, ikke fordi MS SQL gør noget forkert, men fordi MySQL er en snyder. Den tillader, at man "glemmer" at opføre alle medtagne ikke-sum felter i sin GROUP BY og returnerer bare en værdi fra en tilfældig række inden for den gruppe man arbejder med. Det gør i mange tilfælde tingene lidt lettere for programmøren, men lader på den anden side døren stå pivåben for uventede resultater, som ikke kan bruges. Så vær glad for, at SQL server gør det rigtige.
Avatar billede babyworm Nybegynder
10. december 2012 - 10:41 #11
Lukker spørgsmålet.. bare lige giv et svar så får i point :)
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