PDA

Pogčedajte punu verziju : Sumiranje parova


razno
04. 09. 2011., 20:18
Pozdrav,

imam jedan problem na kome sam zakucao.
Najme imam tabelu Skup_proizvoda(ID1,ID2,broj)
ID1 i ID2 referenciraju tabelu proizvodi. Ono sto treba da uradim je da izbacim sumu brojeva za svaki par. Par se moze pojavljivati vise puta. Takodje pod jednim parom se podrazumeva 1|2 i 2|1
Evo primer podatak
ID1|ID2|broj
------------
1|2|10
2|1|20
1|3|5
Ocekivani rezultat treba da bude
ID1|ID2|BROJ
-------------
1|2|30
1|3|5

Resenje treba da bude cist SQL

webarto
04. 09. 2011., 22:04
SELECT t2.id_1, t2.id_2, SUM(t1.broj) broj
FROM dpt t1
LEFT JOIN dpt t2 ON t1.id_1 = t2.id_2
WHERE t1.id_2 = t2.id_1


id_1 id_2 broj
1 2 30

E sad jedino još da selektuje ove single parove...

jablan
04. 09. 2011., 22:21
Ja bih rađe to uradio sa ugnježđenim upitom da dovedem ID1 i ID2 u red, pa onda nad time običan GROUP BY.

Znači nešto na foru
SELECT id1, id2, sum(broj) FROM
(
SELECT
CASE WHEN id1 > id2 THEN id2 ELSE id1 AS id1,
CASE WHEN id1 > id2 THEN id1 ELSE id2 AS id2,
broj
FROM dpt
) a
GROUP BY id1, id2

razno
05. 09. 2011., 00:51
@webarto Ne ispisuje sve redove, tj ispisuje one koji se javljaju u obe varijante dok oni koji su u jednoj ne ispisuje. Hvala u svakom slucaju na odgovoru

@Jablan da to je to resenje.

Sad vidim kako je prosto, ali kad ti nije dan, nije ti :)

webarto
05. 09. 2011., 19:56
Da, napisao sam to :) @jablan, znaš li ti možda da prepraviš ovaj moj query, a da vraća oba rezultata, ili ovaj suprotni :) Hvala.

jablan
06. 09. 2011., 07:31
Teško bogami. Mislim da nije dobar put. Imaš banalan primer, npr da imaš u tabeli


1 2 10
1 2 10
2 1 10
2 1 10


u JOINU ćeš onda imati 8 redova kao rezultat, tj suma će ti biti 80, a ne 40, zar ne?

ivanhoe
06. 09. 2011., 08:37
evo ovako:

SELECT t1.id1, t1.id2, IF(t2.id1, (t1.broj + t2.broj), t1.broj) AS broj
FROM proba t1
LEFT JOIN proba t2 ON (t1.id1 = t2.id2 AND t1.id2 = t2.id1)

razno
06. 09. 2011., 10:24
@ivanhoe Nece bas raditi kako treba. Radi sumiranje lepo, medjutim ne izbacuje duplikate iz rezultata (sto treba).
I ja sam krenuo da resavam sa join-om medjutim zakucao sam na tom delu izbacivanja duplih rezultata :)

jablan
06. 09. 2011., 10:29
evo ovako:

Nisam siguran da razumem ideju:


test=# create table dpt (id1 integer, id2 integer, broj integer);
CREATE TABLE
test=# insert into dpt values (1, 2, 10);
INSERT 0 1
test=# insert into dpt values (1, 2, 10);
INSERT 0 1
test=# insert into dpt values (2, 1, 10);
INSERT 0 1
test=# insert into dpt values (2, 1, 10);
INSERT 0 1
test=# insert into dpt values (1, 3, 10);
INSERT 0 1
test=# SELECT t1.id1, t1.id2, t1.broj + coalesce(t2.broj, 0) AS broj
FROM dpt t1
LEFT JOIN dpt t2 ON (t1.id1 = t2.id2 AND t1.id2 = t2.id1);
id1 | id2 | broj
-----+-----+------
1 | 2 | 20
1 | 2 | 20
1 | 2 | 20
1 | 2 | 20
1 | 3 | 10
2 | 1 | 20
2 | 1 | 20
2 | 1 | 20
2 | 1 | 20
(9 rows)

ivanhoe
06. 09. 2011., 14:58
da, da, nisam pazljivo procitao opis, ne resava se duplikata... mada mora da ima neka fora i ovako, trebalo bi da (skoro) svaki subquery moze da se resi i JOIN-om

EDIT: Evo ovo radi:

SELECT t1.`id1`, t1.id2, t1.broj + coalesce(t2.broj, 0) AS broj
FROM proba t1
LEFT JOIN proba t2 ON (t1.id1 = t2.id2 AND t1.id2 = t2.id1)
GROUP BY IF(t1.id1<t1.id2, t1.id1, t1.id2), IF(t1.id1 > t1.id2, t1.id1, t1.id2)

jablan
06. 09. 2011., 15:25
Jesi li siguran da to daje dobre cifre? Nemam MySQL da probam, a Postgres ne dozvoljava da u SELECT imaš nešto što nemaš u GROUP BY (osim ako nije agregatna funkcija). Zar ne treba da postoji neki SUM()?

webarto
06. 09. 2011., 15:33
Radi ovo od @ivanhoe dobro...

1 2 30
1 3 5

jablan
06. 09. 2011., 15:52
Mislio sam na moj primer podataka:


test=# insert into dpt values (1, 2, 10);
INSERT 0 1
test=# insert into dpt values (1, 2, 10);
INSERT 0 1
test=# insert into dpt values (2, 1, 10);
INSERT 0 1
test=# insert into dpt values (2, 1, 10);
INSERT 0 1
test=# insert into dpt values (1, 3, 10);
INSERT 0 1

webarto
06. 09. 2011., 15:56
Pardon, da, samo sabere prvi par ( 1 <=> 2) i iste, ostale, odbaci :)

ivanhoe
06. 09. 2011., 16:24
pih, al ste picajzle... nemam sad vremena, ali videce vi, napravicu JOIN makar crko :P

webarto
06. 09. 2011., 16:33
Ja sam bio pokušao i sa UNION i sa MINUS i na kraju FAIL :D Problem je ovo SUM što "spljošti", ma može se uraditi 100% ali eto :)

razno
06. 09. 2011., 16:48
Mislim da ovo nikako nece uspeti sa JOIN/UNION, bar ne da radi sve.

Inace ovo je bio ispitni zadatak za 5 od 100 poena sa ETF-a

webarto
06. 09. 2011., 17:32
Znači nismo neki 'akeri :D

jablan
06. 09. 2011., 17:39
U principu, može i bez podupita:


select
case when id1 > id2 then id2 else id1 end as a1,
case when id1 > id2 then id1 else id2 end as a2,
sum(broj)
from dpt
group by a1, a2;


Sa JOINOM može eventualno ako povezuješ bukvalno svaki red sam sa sobom da bi swapovao id1 i id2 (onda treba i veštački ključ da se doda), ali to je nepotrebna komplikacija.

ivanhoe
06. 09. 2011., 18:18
@razno: Vidis, moram te baze da polozim vec jednom...

@jablan: da, da, to je dobra ideja...

razno
07. 09. 2011., 02:29
^Ako su baze 1 u pitanju (Bojovic i Milos Cvetanovic), osim ovih par upita koji se pisu (oko 15% ocene) i malo normalizacije (oko 20% ocene) ostalo nisam video da ima veze sa praksom. Uce se i polazu protokoli zakljucavanja,vremenske marke, moguce vrednosti u transakcijama tokom izvrsavanja itd...nesto sto ja u proteklih 8 godina koliko programiram nisam imao potrebu da koristim. Uglavnom je vise teorija kako je implementirana baza, umesto da ima vise prakse :(
Postoji i baze 2 gde se rade NO SQL baze,ali kako sam cuo nije do sada biran zbog kombinacije profesor + asistent.

ivanhoe
07. 09. 2011., 04:22
Ma da, ostale mi te baze, PRS i jos par ispita, vec jedno 5-6 godina...