De tabelnaam is “OrderDetails” en de kolommen worden hieronder gegeven:
OrderDetailID || ProductID || ProductName || OrderQuantity
Ik probeer meerdere kolommen te selecteren en te groeperen op product-ID terwijl ik SUM of OrderQuantity heb.
Select ProductID,ProductName,OrderQuantity Sum(OrderQuantity)
from OrderDetails Group By ProductID
Maar deze code geeft natuurlijk een foutmelding. Ik moet andere kolomnamen toevoegen om te groeperen op, maar dat is niet wat ik wil en aangezien mijn gegevens veel items bevatten, zijn resultaten op die manier onverwacht.
Voorbeeldgegevensquery:
ProductID,ProductName,OrderQuantity van OrderDetails
Resultaten staan hieronder:
ProductID ProductName OrderQuantity
1001 abc 5
1002 abc 23 (ProductNames can be same)
2002 xyz 8
3004 ytp 15
4001 aze 19
1001 abc 7 (2nd row of same ProductID)
Verwacht resultaat:
ProductID ProductName OrderQuantity
1001 abc 12 (group by productID while summing)
1002 abc 23
2002 xyz 8
3004 ytp 15
4001 aze 19
Hoe selecteer ik meerdere kolommen en de kolom Groeperen op ProductID, aangezien ProductName niet uniek is?
Terwijl u dat doet, krijgt u ook de som van de kolom OrderQuantity.
Antwoord 1, autoriteit 100%
Ik gebruik deze truc om op één kolom te groeperen als ik een selectie met meerdere kolommen heb:
SELECT MAX(id) AS id,
Nume,
MAX(intrare) AS intrare,
MAX(iesire) AS iesire,
MAX(intrare-iesire) AS stoc,
MAX(data) AS data
FROM Produse
GROUP BY Nume
ORDER BY Nume
Dit werkt.
Antwoord 2, autoriteit 8%
Uw gegevens
DECLARE @OrderDetails TABLE
(ProductID INT,ProductName VARCHAR(10), OrderQuantity INT)
INSERT INTO @OrderDetails VALUES
(1001,'abc',5),(1002,'abc',23),(2002,'xyz',8),
(3004,'ytp',15),(4001,'aze',19),(1001,'abc',7)
Query
Select ProductID, ProductName, Sum(OrderQuantity) AS Total
from @OrderDetails
Group By ProductID, ProductName ORDER BY ProductID
Resultaat
╔═══════════╦═════════════╦═══════╗
║ ProductID ║ ProductName ║ Total ║
╠═══════════╬═════════════╬═══════╣
║ 1001 ║ abc ║ 12 ║
║ 1002 ║ abc ║ 23 ║
║ 2002 ║ xyz ║ 8 ║
║ 3004 ║ ytp ║ 15 ║
║ 4001 ║ aze ║ 19 ║
╚═══════════╩═════════════╩═══════╝
Antwoord 3, autoriteit 8%
Ik wilde alleen een effectievere en algemenere manier toevoegen om dit soort problemen op te lossen.
Het belangrijkste idee gaat over het werken met subquery’s.
doe je groep op en sluit je aan bij dezelfde tafel op de ID van de tafel.
uw geval is specifieker omdat uw product-ID niet uniekis, dus er zijn 2 manieren om dit op te lossen.
Ik zal beginnen met de meer specifieke oplossing:
Aangezien uw product-ID niet uniekis, hebben we een extra stap nodig, namelijk het selecteren van DISCTINCT
product-ID’s na het groeperen en het uitvoeren van de subquery als volgt:
WITH CTE_TEST AS (SELECT productId, SUM(OrderQuantity) Total
FROM OrderDetails
GROUP BY productId)
SELECT DISTINCT(OrderDetails.ProductID), OrderDetails.ProductName, CTE_TEST.Total
FROM OrderDetails
INNER JOIN CTE_TEST ON CTE_TEST.ProductID = OrderDetails.ProductID
dit levert precies op wat er wordt verwacht
ProductID ProductName Total
1001 abc 12
1002 abc 23
2002 xyz 8
3004 ytp 15
4001 aze 19
Maarer is een schonere manier om dit te doen. Ik denk dat ProductId
een refererende sleutel is voor de producttabel en ik denk dat er een OrderId
primaire sleutel(uniek) in deze tabel moet staan.
in dit geval hoeft u maar een paar stappen te ondernemen om extra kolommen op te nemen terwijl u op slechts één kolommen groepeert. Het zal dezelfde oplossing zijn als de volgende
Laten we deze t_Value
tabel als voorbeeld nemen:
Als ik wil groeperen op beschrijving en ook alle kolommen wil weergeven.
Het enige wat ik hoef te doen is:
- maak
WITH CTE_Name
subquery met uw GroupBy-kolom en COUNT-voorwaarde - selecteer alles (of wat u ook wilt weergeven) uit de waardetabel en het totaal uit de CTE
INNER JOIN
met CTE in de kolom ID(primaire sleutel of unieke beperking)
en dat is het!
Hier is de vraag
WITH CTE_TEST AS (SELECT Description, MAX(Id) specID, COUNT(Description) quantity
FROM sch_dta.t_value
GROUP BY Description)
SELECT sch_dta.t_Value.*, CTE_TEST.quantity
FROM sch_dta.t_Value
INNER JOIN CTE_TEST ON CTE_TEST.specID = sch_dta.t_Value.Id
En hier is het resultaat:
Antwoord 4, autoriteit 3%
mysqlGROUP_CONCAT
-functie kan https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_group-concat
SELECT ProductID, GROUP_CONCAT(DISTINCT ProductName) as Names, SUM(OrderQuantity)
FROM OrderDetails GROUP BY ProductID
Dit zou terugkeren:
ProductID Names OrderQuantity
1001 red 5
1002 red,black 6
1003 orange 8
1004 black,orange 15
Vergelijkbaar idee als degene die @Urs Marian hier plaatste https://stackoverflow.com/a/38779277/906265
Antwoord 5, autoriteit 2%
WITH CTE_SUM AS (
SELECT ProductID, Sum(OrderQuantity) AS TotalOrderQuantity
FROM OrderDetails GROUP BY ProductID
)
SELECT DISTINCT OrderDetails.ProductID, OrderDetails.ProductName, OrderDetails.OrderQuantity,CTE_SUM.TotalOrderQuantity
FROM
OrderDetails INNER JOIN CTE_SUM
ON OrderDetails.ProductID = CTE_SUM.ProductID
Controleer of dit werkt.
Antwoord 6, autoriteit 2%
Je kunt dit proberen:
Select ProductID,ProductName,Sum(OrderQuantity)
from OrderDetails Group By ProductID, ProductName
U hoeft alleen kolommen te Group By
die geen statistische functie hebben in de Select
-clausule. U kunt in dit geval dus gewoon Group By
ProductID en ProductName gebruiken.
Antwoord 7, autoriteit 2%
U kunt de onderstaande zoekopdracht proberen. Ik neem aan dat je één tabel hebt voor al je gegevens.
SELECT OD.ProductID, OD.ProductName, CalQ.OrderQuantity
FROM (SELECT DISTINCT ProductID, ProductName
FROM OrderDetails) OD
INNER JOIN (SELECT ProductID, OrderQuantity SUM(OrderQuantity)
FROM OrderDetails
GROUP BY ProductID) CalQ
ON CalQ.ProductID = OD.ProductID
Antwoord 8, autoriteit 2%
Naar mijn mening is dit een ernstige taalfout waardoor SQL lichtjaren achterloopt op andere talen. Dit is mijn ongelooflijk hacky-oplossing. Het is een hele klus, maar het werkt altijd.
Voordat ik dat doe, wil ik de aandacht vestigen op het antwoord van @Peter Mortensen, dat naar mijn mening het juiste antwoord is. De enige reden waarom ik in plaats daarvan het onderstaande doe, is omdat de meeste implementaties van SQL ongelooflijk trage join-bewerkingen hebben en je dwingen te breken “herhaal jezelf niet”. Ik wil dat mijn vragen snel worden ingevuld.
Dit is ook een oude manier om dingen te doen. STRING_AGGen STRING_SPLITzijn een stuk schoner. Nogmaals, ik doe het op deze manier omdat het altijd werkt.
-- remember Substring is 1 indexed, not 0 indexed
SELECT ProductId
, SUBSTRING (
MAX(enc.pnameANDoq), 1, CHARINDEX(';', MAX(enc.pnameANDoq)) - 1
) AS ProductName
, SUM ( CAST ( SUBSTRING (
MAX(enc.pnameAndoq), CHARINDEX(';', MAX(enc.pnameANDoq)) + 1, 9999
) AS INT ) ) AS OrderQuantity
FROM (
SELECT CONCAT (ProductName, ';', CAST(OrderQuantity AS VARCHAR(10)))
AS pnameANDoq, ProductID
FROM OrderDetails
) enc
GROUP BY ProductId
Of in gewone taal:
- Lijm alles behalve één veld samen tot een string met een scheidingsteken waarvan je weet dat het niet zal worden gebruikt
- Gebruik subtekenreeks om de gegevens te extraheren nadat ze zijn gegroepeerd
Wat betreft prestaties Ik heb altijd superieure prestaties gehad door snaren te gebruiken in plaats van bijvoorbeeld bigints. Met microsoft en oracle is substring tenminste een snelle operatie.
Dit vermijdt de problemen die u tegenkomt wanneer u MAX() gebruikt, waarbij wanneer u MAX() op meerdere velden gebruikt, ze niet langer overeenkomen en uit verschillende rijen komen. In dit geval worden uw gegevens gegarandeerd precies zo aan elkaar gelijmd als u had gevraagd.
Om toegang te krijgen tot een 3e of 4e veld, heb je geneste substrings nodig, “zoek na de eerste puntkomma een 2e”. Daarom is STRING_SPLIT beter als het beschikbaar is.
Opmerking: Hoewel dit buiten het bestek van uw vraag valt, is dit vooral handig wanneer u zich in de tegenovergestelde situatie bevindt en u groepeert op een gecombineerde sleutel, maar niet wilt dat elke mogelijke permutatie wordt weergegeven, dat wil zeggen dat u ‘ wilt blootleggen ‘ foo’ en ‘bar’ als een gecombineerde sleutel maar wil groeperen op ‘foo’
Antwoord 9
==EDIT==
Ik heb je vraag opnieuw gecontroleerd en ben tot de conclusie gekomen dat dit niet kan.
Productnaam is niet uniek, het moet deel uitmaken van de Group By
of worden uitgesloten van uw resultaten.
Hoe zou SQL deze resultaten bijvoorbeeld aan u presenteren als u Group By
alleen ProductID?
ProductID | ProductName | OrderQuantity
---------------------------------------
1234 | abc | 1
1234 | def | 1
1234 | ghi | 1
1234 | jkl | 1
Antwoord 10
Ik had een soortgelijk probleem als de OP. Toen zag ik het antwoord van @Urs Marian, wat veel heeft geholpen.
Maar daarnaast was ik op zoek naar, wanneer er meerdere waarden in een kolom zijn en ze worden gegroepeerd, hoe ik de laatst ingediende waarde kan krijgen (bijvoorbeeld gesorteerd op een datum/id-kolom).
Voorbeeld:
We hebben de volgende tabelstructuur:
CREATE TABLE tablename(
[msgid] [int] NOT NULL,
[userid] [int] NOT NULL,
[username] [varchar](70) NOT NULL,
[message] [varchar](5000) NOT NULL
)
Er staan nu minstens twee datasets in de tabel:
+-------+--------+----------+---------+
| msgid | userid | username | message |
+-------+--------+----------+---------+
| 1 | 1 | userA | hello |
| 2 | 1 | userB | world |
+-------+--------+----------+---------+
Daarom werkt het volgende SQL-script (aangevinkt op MSSQL) om het te groeperen, ook als hetzelfde gebruikers-ID verschillende gebruikersnaamwaarden heeft. In het onderstaande voorbeeld wordt de gebruikersnaam met de hoogste msgstr getoond:
SELECT m.userid,
(select top 1 username from table where userid = m.userid order by msgid desc) as username,
count(*) as messages
FROM tablename m
GROUP BY m.userid
ORDER BY count(*) DESC
Antwoord 11
SELECT ProductID, ProductName, OrderQuantity, SUM(OrderQuantity) FROM OrderDetails WHERE(OrderQuantity) IN(SELECT SUM(OrderQuantity) FROM OrderDetails GROUP BY OrderDetails) GROUP BY ProductID, ProductName, OrderQuantity;
Ik heb de bovenstaande oplossing gebruikt om een soortgelijk probleem in Oracle12c op te lossen.