Avatar billede stephanryer Nybegynder
23. maj 2007 - 11:03 Der er 32 kommentarer og
1 løsning

SELECT, DISTINCT og SUM

ID  Navn  Beløb
1  Jens    30,00
1  Mark    30,00
1  Janus    30,00
2  Karina  20,00
2  Martin  20,00
3  Frederik 60,00
3  Tim      60,00
4  Hans    20,00
4  Viggo    20,00

Betragt ovenstående tabel. Denne er en forenkling af mit problem og skal repræsentere en joinet tabel.

Mit spørgsmål er nu, hvordan jeg laver en sum på Beløb, som kun lægger beløb sammen hvor ID er forskelligt.

Jeg kan jo ikke sige SUM(DISTINCT Beløb), da jeg vil have 20,00 med to gange, da denne optræder både med id 2 og 4.

Findes der en måde at tage SUM på, hvor man laver noget a la DISTINCT på ID?



På forhånd tak
Avatar billede -mundi- Nybegynder
23. maj 2007 - 11:11 #1
har du prøvet select SUM(Beløb)as total,id group by id
Avatar billede stephanryer Nybegynder
23. maj 2007 - 11:18 #2
jeg skal ikke GROUP by ID.

Jeg skal group det hele samme til én record.

Kan lige prøve at udvide eksemplet:

ID  Navn    Postnr  Beløb
1  Jens      8000    30,00
1  Mark      8000    30,00
1  Janus    8000    30,00
2  Karina    8000    20,00
2  Martin    8000    20,00
3  Frederik  9000    60,00
3  Tim      9000    60,00
4  Hans      9000    20,00
4  Viggo    9000    20,00

Jeg vil her gerne lave en group by Postnr, som Summerer beløbene sammen, hvor ID er forskellige.
Avatar billede stephanryer Nybegynder
23. maj 2007 - 11:19 #3
ALtså dvs jeg vil gerne ende med:

Postnr  Sum
8000    50,00
9000    80,00
Avatar billede bauerdata Nybegynder
23. maj 2007 - 11:27 #4
select postnr, sum(belob)
from tabel
group by postnr
Avatar billede -mundi- Nybegynder
23. maj 2007 - 11:49 #5
select sum(t2.beløb),t2.postnr from (select distinct(beløb,postnr,id)) t2 group by t2.postnr

noget i den stil måske ? Der er vist lidt syntaxfejl :-)
Avatar billede stephanryer Nybegynder
23. maj 2007 - 12:01 #6
-mundi-

Kan det ikke gøres uden sub-select? Jeg har nemlig en rimelig kompleks SQL-query, som jeg ikke ønsker at tilføje subqueries til, da dette vil gå ud over performance.
Avatar billede -mundi- Nybegynder
23. maj 2007 - 12:04 #7
så vidt jeg kan se er det enten en subselect eller en cursor.
Nu ved jeg jo ikke hvor mange records du arbejder på, men der burde ikke ske det store performance drop ved det.
Avatar billede 0xffff Nybegynder
23. maj 2007 - 12:20 #8
uhm... hvad med at prøve med roll up ?

select postnr, sum(belob)
from tabel
group by postnr
with roll up
Avatar billede bauerdata Nybegynder
23. maj 2007 - 12:30 #9
vil du venligst komme med eksempel på de data du ønsker skal være et resultat af forespørgslen ?
ID  Navn    Postnr  Beløb
1  Jens      8000    30,00
1  Mark      8000    30,00
1  Janus    8000    30,00
2  Karina    8000    20,00
2  Martin    8000    20,00
3  Frederik  9000    60,00
3  Tim      9000    60,00
4  Hans      9000    20,00
4  Viggo    9000    20,00

sql bla bla.
output
Postnr  Sum
8000    50,00
9000    80,00

Det her passer ikke , hvis du kan udtrykke hvad du vil have kan vi hjælpe dig
Avatar billede stephanryer Nybegynder
23. maj 2007 - 12:59 #10
Jo det gør. Jeg vil have en sum på Beløbet, men kun hvor ID'et er forskelligt.

Altså jeg vil kun have 30,00 én gang, da ID i alle tre kolonner er det samme.
Avatar billede bauerdata Nybegynder
23. maj 2007 - 15:02 #11
Hvordan ser dine grundtabeller ud.
Avatar billede arne_v Ekspert
23. maj 2007 - 17:45 #12
jeg tror at mundi har ret

SELECT postnr,SUM(beloeb) FROM (SELECT id,MAX(postnr) as postnr,MAX(beloeb) AS beloeb FROM tabel) x GROUP BY postnr
Avatar billede arne_v Ekspert
23. maj 2007 - 18:03 #13
bemaerk at med en normaliseret database struktur ville det have vaeret simpelt ...
Avatar billede stephanryer Nybegynder
23. maj 2007 - 18:23 #14
Det er skam normaliseret. Det udtræk jeg har her er blot et mellemresultat.

Lad min vise et andet eksempel:

Jeg har en følgende tabeller:

ordre
OrdreID  Navn    Dato      TrukketBeløb
1        Hans    1-2-2007  50,00
2        Jens    1-2-2007  40,00
3        Signe  2-2-2007  80,00
4        Frank  2-2-2007  20,00

Ordrelinje
LinjeID  OrdreID  VareID  StkPris  Antal
1        1        123    50,00    2
2        1        412    20,00    3
3        2      382    40,00    1
4        3      421    35,00    3
5        4      482    40,00    1
6        4      321    20,00    1


Jeg vil nu gerne have vist antallet af ordre pr. dag, samlet antal bestilte varer pr dag samt det trukkede beløb således:

Dato      AntalOrdrer  AntalVarer  SamletTrukketBeløb
1-2-2007  2            6          90,00
2-2-2007  2          5          100,00
Avatar billede 0xffff Nybegynder
23. maj 2007 - 18:42 #15
jeg vil gen-iterere hvad jeg skrev tidligere. Prøv med "with rollup". Det er lige præcis de situationer den er der for. Den laver undersummeringer.
Avatar billede stephanryer Nybegynder
23. maj 2007 - 18:56 #16
forstår ikke brugen af roll up. Kan du forklar lidt nærmere?
Avatar billede kjulius Novice
23. maj 2007 - 23:12 #17
Ku' du ikke bare skrive sådan?

SELECT o.Dato, COUNT(DISTINCT o.OrdreID) AS AntalOrdrer, COUNT(DISTINCT ol.VareID) AS AntalVarer, SUM(ol.Antal) AS AntalPakninger, SUM(o.TrukketBeløb) AS SamletTrukketBeløb
FROM ordre o
INNER JOIN Ordrelinie ol ON ol.OrdreID = o.OrdreID
GROUP BY o.Dato
Avatar billede kjulius Novice
23. maj 2007 - 23:39 #18
Okay, jeg har måske lige lavet en lille fejl. Det samlede trukne beløb kan vist ikke laves som en opsummering på o.TrukketBeløb. Da der bliver lavet en join til ordrelinierne, returneres der jo det antal rækker der er heri. Derfor skal det nok snarere laves som:

SELECT o.Dato, COUNT(DISTINCT o.OrdreID) AS AntalOrdrer, COUNT(DISTINCT ol.VareID) AS AntalVarer, SUM(ol.Antal) AS AntalPakninger, SamletTrukketBeløb
FROM (
  SELECT Dato, SUM(TrukketBeløb) AS SamletTrukketBeløb
  FROM ordre
  GROUP BY Dato
) AS os
INNER JOIN Ordre o ON o.Dato = os.Dato
INNER JOIN Ordrelinje ol ON ol.OrdreID = o.OrdreID
GROUP BY o.Dato
Avatar billede arne_v Ekspert
24. maj 2007 - 04:13 #19
SELECT dato,COUNT(*),(SELECT COUNT(*) FROM ordrelinie WHERE ordrelinie.ordreid=ordre.ordreid),SUM(trukketbeløb)
FROM ordre

måske
Avatar billede arne_v Ekspert
24. maj 2007 - 04:13 #20
SELECT dato,COUNT(*),(SELECT COUNT(*) FROM ordrelinie WHERE ordrelinie.ordreid=ordre.ordreid),SUM(trukketbeløb)
FROM ordre
GROUP BY dato
Avatar billede stephanryer Nybegynder
24. maj 2007 - 14:28 #21
Har ikke testet sætningen, men umiddelbart ville jeg ikke synes en ville kunne afvikles.


...,(SELECT COUNT(*) FROM ordrelinie WHERE ordrelinie.ordreid=ordre.ordreid),...

Her vil ordre jo ikke kunne identificeres, da det er en subquery.
Avatar billede arne_v Ekspert
24. maj 2007 - 15:39 #22
jeg mener at subqueries i select listen har adgang til tabeller i from

men som de siger i TV reklamer: proev det !
Avatar billede stephanryer Nybegynder
24. maj 2007 - 15:58 #23
:) Well jeg har prøvet det før uden held.
Avatar billede arne_v Ekspert
25. maj 2007 - 04:03 #24
lidt test viser at ordre er i scope men at ordre.ordreid giver problemer fordi den
ikke er i GROUP BY

¤#"!#"¤#¤!

lidt eksperimenteret giver imidlertid 2 som virker:

SELECT oo.dato,
      COUNT(*),
      (SELECT SUM(antal) FROM ordrelinie WHERE ordrelinie.ordreid IN (SELECT ordreid FROM ordre io WHERE io.dato=oo.dato)),
      SUM(oo.trukketbeloeb)
FROM ordre oo
GROUP BY dato

og

SELECT oo.dato,
      COUNT(DISTINCT oo.ordreid),
      SUM(antal),(SELECT SUM(trukketbeloeb) FROM ordre io WHERE io.dato=oo.dato)
FROM ordre oo JOIN ordrelinie ON oo.ordreid=ordrelinie.ordreid
GROUP BY dato
Avatar billede arne_v Ekspert
25. maj 2007 - 04:04 #25
1> CREATE TABLE ordre(ordreid INTEGER NOT NULL PRIMARY KEY,
2>                    navn VARCHAR(50),
3>                    dato DATETIME,
4>                    trukketbeloeb DECIMAL(12,2)
5> )
6> GO
1> CREATE TABLE ordrelinie(linieid INTEGER NOT NULL PRIMARY KEY,
2>                        ordreid INTEGER,
3>                        vareid INTEGER,
4>                        stkpris DECIMAL(12,2),
5>                        antal INTEGER
6> )
7> GO
1> INSERT INTO ordre VALUES(1,'Hans','1-2-2007',50.00)
2> GO
(1 row affected)
1> INSERT INTO ordre VALUES(2,'Jens','1-2-2007',40.00)
2> GO
(1 row affected)
1> INSERT INTO ordre VALUES(3,'Signe','2-2-2007',80.00)
2> GO
(1 row affected)
1> INSERT INTO ordre VALUES(4 ,'Frank','2-2-2007',20.00)
2> GO
(1 row affected)
1> INSERT INTO ordrelinie VALUES(1,1,123,50.00,2)
2> GO
(1 row affected)
1> INSERT INTO ordrelinie VALUES(2,1,412,20.00,3)
2> GO
(1 row affected)
1> INSERT INTO ordrelinie VALUES(3,2,382,40.00,1)
2> GO
(1 row affected)
1> INSERT INTO ordrelinie VALUES(4,3,421,35.00,3)
2> GO
(1 row affected)
1> INSERT INTO ordrelinie VALUES(5,4,482,40.00,1)
2> GO
(1 row affected)
1> INSERT INTO ordrelinie VALUES(6,4,321,20.00,1)
2> GO
(1 row affected)
1> SELECT oo.dato,
2>        COUNT(*),
3>        (SELECT SUM(antal) FROM ordrelinie WHERE ordrelinie.ordreid IN (SELECT
ordreid FROM ordre io WHERE io.dato=oo.dato)),
4>        SUM(oo.trukketbeloeb)
5> FROM ordre oo
6> GROUP BY dato
7> GO
dato

----------------------- ----------- -----------
        ----------------------------------------
2007-01-02 00:00:00.000          2          6
                                          90.00
2007-02-02 00:00:00.000          2          5
                                          100.00

(2 rows affected)
1> SELECT oo.dato,
2>        COUNT(DISTINCT oo.ordreid),
3>        SUM(antal),(SELECT SUM(trukketbeloeb) FROM ordre io WHERE io.dato=oo.d
ato)
4> FROM ordre oo JOIN ordrelinie ON oo.ordreid=ordrelinie.ordreid
5> GROUP BY dato
6> GO
dato

----------------------- ----------- -----------
        ----------------------------------------
2007-01-02 00:00:00.000          2          6
                                          90.00
2007-02-02 00:00:00.000          2          5
                                          100.00

(2 rows affected)
1> DROP TABLE ordrelinie
2> GO
1> DROP TABLE ordre
2> GO
Avatar billede stephanryer Nybegynder
25. maj 2007 - 08:45 #26
Mange tak. Læg et svar :)

Dog var jeg på udkig efter en løsning, der ikke benytter Sub-queries, men nu du har brugt så meget tid på besvarelsen synes jeg det må være på plads med point.

Jeg vil benytte denne løsning til mit problem.
Avatar billede kjulius Novice
25. maj 2007 - 15:56 #27
--> stephanryer:
Du har slet ikke kommenteret på mine indlæg. Gav den fejlmeldinger eller forkert resultat?
Avatar billede stephanryer Nybegynder
25. maj 2007 - 19:15 #28
kjulius: Jeg har ikke haft tid til at teste det, men da alle løsninger indeholder subqueries vil jeg vælge en af dem og give jer alle point.

I skal have mange tak for hjælpen :)
Avatar billede arne_v Ekspert
26. maj 2007 - 03:26 #29
kjulius>

Jeg har jo data så jeg kan nemt teste. Den sidste virker med en lille ændring (tilføjelse
til GROUP BY):

1> SELECT o.Dato, COUNT(DISTINCT o.OrdreID) AS AntalOrdrer, COUNT(DISTINCT ol.Va
reID) AS AntalVarer, SUM(ol.Antal) AS AntalPakninger, SUM(o.TrukketBeloeb) AS Sa
mletTrukketBeloeb
2> FROM ordre o
3> INNER JOIN Ordrelinie ol ON ol.OrdreID = o.OrdreID
4> GROUP BY o.Dato
5> GO
Dato                    AntalOrdrer AntalVarer  AntalPakninger
        SamletTrukketBeloeb
----------------------- ----------- ----------- --------------
        ----------------------------------------
2007-01-02 00:00:00.000          2          3              6
                                          140.00
2007-02-02 00:00:00.000          2          3              5
                                          120.00

(2 rows affected)
1> SELECT o.Dato, COUNT(DISTINCT o.OrdreID) AS AntalOrdrer, COUNT(DISTINCT ol.Va
reID) AS AntalVarer, SUM(ol.Antal) AS AntalPakninger, SamletTrukketBeloeb
2> FROM (
3>  SELECT Dato, SUM(TrukketBeloeb) AS SamletTrukketBeloeb
4>  FROM ordre
5>  GROUP BY Dato
6> ) AS os
7> INNER JOIN Ordre o ON o.Dato = os.Dato
8> INNER JOIN Ordrelinie ol ON ol.OrdreID = o.OrdreID
9> GROUP BY o.Dato
10> GO
Msg 8120, Level 16, State 1, Server ARNEPC3, Line 1
Column 'os.SamletTrukketBeloeb' is invalid in the select list because it is not
contained in either an aggregate function or the GROUP BY clause.
1> SELECT o.Dato, COUNT(DISTINCT o.OrdreID) AS AntalOrdrer, COUNT(DISTINCT ol.Va
reID) AS AntalVarer, SUM(ol.Antal) AS AntalPakninger, SamletTrukketBeloeb
2> FROM (
3>  SELECT Dato, SUM(TrukketBeloeb) AS SamletTrukketBeloeb
4>  FROM ordre
5>  GROUP BY Dato
6> ) AS os
7> INNER JOIN Ordre o ON o.Dato = os.Dato
8> INNER JOIN Ordrelinie ol ON ol.OrdreID = o.OrdreID
9> GROUP BY o.Dato,os.SamletTrukketBeloeb
10> GO
Dato                    AntalOrdrer AntalVarer  AntalPakninger
        SamletTrukketBeloeb
----------------------- ----------- ----------- --------------
        ----------------------------------------
2007-01-02 00:00:00.000          2          3              6
                                          90.00
2007-02-02 00:00:00.000          2          3              5
                                          100.00

(2 rows affected)
Avatar billede arne_v Ekspert
26. maj 2007 - 03:27 #30
og et svar fra mig
Avatar billede kjulius Novice
27. maj 2007 - 11:40 #31
--> Nå ja, selvfølgelig (slår mig for panden) - det er jo indlysende...
Tak for analysen. :-)

Med det arbejde du har lagt i opgaven, fortjener du at pointene...
Avatar billede kjulius Novice
27. maj 2007 - 12:04 #32
I øvrigt er det ikke helt rigtigt, at alle foreslåede løsninger baserer sig på subqueries. Min baserer sig i stedet på nested joins, hvilket ikke er det samme.
Avatar billede stephanryer Nybegynder
21. juni 2007 - 09:49 #33
I skal alle have tak for hjælpen :)
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