Šta je novo?

Slozeni Upit!?

mariaana

Čuven
Učlanjen(a)
23.02.2003
Poruke
67
Poena
609
Kako iz baze dobiti izvestaj koji daje broj slogova koji zadovoljavaju kriterijum za jedno polje, ali za vise opsega. Pa sve to jos zakomlikovano sa grupisanjem po nekom drugom polju (recimo GRUPA)?
Evo ga jednostavan primer:

Tabela LJUDI sa poljima ID, GRUPA, GODINE. Pokazi broj ljudi po grupama mladjih od 20 god.
--------------------------------------------------------------------------------
select GRUPA, COUNT(*)
from LJUDI
where GODINE < 20
group by GRUPA
--------------------------------------------------------------------------------
Ali sta ako za izvestaj hocu vise opsega: <20, 20 - 30, 30 - 40, itd. Da li postoji slozeni upit koji ovo moze odjednom da izbaci, ili poteram upit vise puta a podatke pamtim (gde??) i na kraju formiram izvestaj.

Inace radim u Delphiju i borim se sa IB SQL Server bazom.
 
Da li ti radi posao unija, npr.
--------------------------------------------------------------------------------
select GRUPA, COUNT(*) AS UKUPNO_PRVI_KRITERIJUM
from LJUDI
where GODINE < 20
group by GRUPA
UNION
select GRUPA, COUNT(*) AS UKUPNO_DRUGI_KRITERIJIUM
from LJUDI
where GODINE BETWEEN 20 AND 30
UNION
select GRUPA, COUNT(*) AS UKUPNO_TRECI_KRITERIJIUM
from LJUDI
where GODINE BETWEEN 30 AND 40
itd.
--------------------------------------------------------------------------------
a posle prezentiras podatke u izvestaju.
Moze i drugacije da se resi, sa vise upita...
 
ssteva je napisao(la):
Da li ti radi posao unija, npr.
--------------------------------------------------------------------------------
select GRUPA, COUNT(*) AS UKUPNO_PRVI_KRITERIJUM
from LJUDI
where GODINE < 20
group by GRUPA
UNION
select GRUPA, COUNT(*) AS UKUPNO_DRUGI_KRITERIJIUM
from LJUDI
where GODINE BETWEEN 20 AND 30
UNION
select GRUPA, COUNT(*) AS UKUPNO_TRECI_KRITERIJIUM
from LJUDI
where GODINE BETWEEN 30 AND 40
itd.
--------------------------------------------------------------------------------
a posle prezentiras podatke u izvestaju.
Moze i drugacije da se resi, sa vise upita...

UNION ne radi posao. On sve COUNT-e trpa u jednu kolonu, bez obzira sto si im dao razlicita imena tako da bi rezultat upita izgledao otprilike:

--------------------------------------------------------------------------------

GRUPA UKUPNO_KRITERIJUM_1
1 4
1 7
1 12
1 9
2 2
2 7
2 1
2 14
3 5
3 8
3 6
3 2
.............

--------------------------------------------------------------------------------
Ja sam ga resio tako sto sam jednostavan upit poterao vise puta sa raznim parametrima, a rezultate sam ubacivao u posebnu tabelu IZVESTAJ koju sam samo za tu svrhu napravio u bazi (i koju obavezno praznim celu i na pocetku i na kraju posle stampanja izvestaja). To vrsi posao, ali ne znam da li je OK resenje, i ne znam kako bi to funkcionisalo u multiuser okruzenju, kad bi vise klijenata napalo ovu tabelu istovremeno bilo bi svasta:D al to je vec drugo teorijsko pitanje...
 
Svaki korisnik formira svoju pomocnu tabela sa kvazi-unikatnim imenom. Tako da svaki korisnik ima svoju tabelu . Nije elegantno, al radi. Kasnije je obrishesh.
 
Yes Cale,

Pretpostavljam da je to neko prilicno uredno resenje ovog problema. Samo sto bi trebalo ovu tabelu brisati i na pocetku (ako_postoji), zbog havarijskih situacija (sistem padne sa kreiranom tabelom na serveru). Treba i tabeli proslediti neko jedinstveno ime (preko nekog parametra) sto sve zahteva malo bolje poznavanje SQL-a nego sto ja trenutno mogu da pruzim:p
 
mariaana je napisao(la):
... Samo sto bi trebalo ovu tabelu brisati i na pocetku (ako_postoji), zbog havarijskih situacija (sistem padne sa kreiranom tabelom na serveru)...

Ime tabele se dobija sa nekim pseudosluchajnim generatorom ( na zahtev za kreiranjem ti vrati otprilike nesto tipa "45afdjk87sg3" i to koristish kao ime ali sa ukljuchenim-programski definisanim ALIAS imenom pri kasnijem korischenju-juziranju tabele), tako da i ako pukne sistem tabela ostaje na serveru , ali poshto je ime uvek neko novo-drugo, ti nemash potrebe da se sekiras zbog toga. Naravno, ta tabela se u normalnom radu posle upotrebe odmah brishe.
 
Nadam se da je ovo odgovor:
select grupa, count(*), godine
from ljudi
group by grupa,
godine
having godine in (20,30)

Rezultat upita:
GRUPA COUNT(*) GODINE
---------- ---------- ----------
1 2 20
2 2 20
2 1 30
1 2 30

U tabeli su podaci:
ID GRUPA GODINE
---------- ---------- ----------
1 1 20
2 1 30
3 2 20
4 2 40
1 1 20
2 1 30
3 2 20
4 2 30
5 2 50

Molim vas zanemarite to sto id nije unique... Pozdrav
 
naravno u HAVING stavis kakav god uslov hoces...
 
Kendy

Malo si pogresno postavio stvari. Vrednost GODINA u tabeli moze da bude bilo koja (15, 20, 21, 22, 24, 27, 30, 31, 32....) a ne samo 20, 30.

Drugo, mnogo vaznije, tvoj upit je grupisan po GRUPA, a u select trazis sumarno polje COUNT(*) i polje GODINA. Kad se izvrsava ovaj SQL on pokusava da grupise sve sa istom vrednoscu GRUPA. Medjutim posto vrednost GODINA u ovim slogovima nije ista tu SQL pada (garantovano :confused: ). Znaci upit
[code:1]
select GODINE, COUNT(*)
from LJUDI
group by GRUPA
[/code:1]
nece nigde proci, dok
[code:1]
select GRUPA, COUNT(*)
from LJUDI
group by GRUPA
[/code:1]
vec ima smisla, i njega posle mozes da nadogradjujes uslovima, vec kako ti treba...
 
Detaljniji odogovor sutra kad budem na poslu, a trenutno mogu da ti kazem da mi se cini da se nismo razumeli:
1. Nisam pretpostavio da treba uzeti sve vrednosti godina koje se pojavljuju u tabeli... ispravicu
2. Sve sto se nalazi u prethodnom postu je COPY/PASTE iz terminal emulatora u kojem je pokrenut SQL*Plus, tako da upit koji sam napisao radi i ne pisem nista proizvoljno...

Posto trenutno nemam gde da probam, pravi odgovor ces dobiti u sledecem postu, ali te molim da mi ponovo, sto preciznije , objasnis sta ti treba... Problem mi ne lici na nesto preterano komplikovano. Dakle, ako dobro objasnis - dobijes dobar odgovor...

Ajd poz & keep cool!
 
OK, ajmo iz pocetka.
Recimo da su u tabeli podaci
[code:1]
ID GRUPA GODINE
-----------------------
1 1 23
2 2 17
3 2 48
4 2 35
5 1 22
6 1 32
7 2 41
8 2 20
9 1 33
10 2 26
11 1 45
[/code:1]
sta bi dao upit
select GRUPA, COUNT(*)
from LJUDI
group by GRUPA

[code:1]
GRUPA COUNT
-----------------
1 5
2 6
[/code:1]
To je u redu, a sta bi trebalo da prikaze upit
select GRUPA, COUNT(*), GODINE
from LJUDI
group by GRUPA

[code:1]
GRUPA COUNT GODINE
----------------------
1 5 ??
2 6 ??
[/code:1]
Ne znam na cemu si ti to dobio rezultat takvog upita i koja je verzija SQL-a (ja radim u ISQL-u - IB Server), ali zamisli da si ti kompjuter i da ti administrator/korisnik postavi ovakvo pitanje - sta bi mu odgovorio ??
Nisam mislio da pametujem (ne bih trazio pomoc da mislim da sam SQL majstor), ali ne verujem da bilo koja verzija SQL-a moze da odgovori na ovaj upit (osim sa Error....). Proveri jos jednom sa malo realnijim podacima u tabeli.

Inace, ako nisam bio jasan na pocetku, meni treba izvestaj iz ove tabele:
[code:1]
GRUPA do20 21-30 31-40 >40
--------------------------------
1 0 2 2 1
2 1 2 1 2
[/code:1]
Pozdrav!:wave;
 
Pardon Kendy

Tek sad sam video da tvoj upit grupise po GRUPA, GODINE (ovo drugo ti je otislo u novi red pa ga nisam ni konstatovao). Mislio sam da grupises samo po GRUPA, pa ti je jasno otkud moj (pogresan) komentar.

Ovako mozda i napravis neko resenje, s tim sto ce having uslov morati da se zakomplikuje...

Izvini jos jednom!:wave;
 
Najzad stigoh...

Evo resenja:

Podaci u tabeli:
[code:1]
ID GRUPA GODINE
--------- --------- ---------
1 1 20
2 1 25
3 2 24
4 2 23
5 2 40
6 1 35
7 1 46
[/code:1]
Upit:
[code:1]
select grupa, count("20-30") "20-30", count("31-40") "31-40", count("41-50") "41-50", count(*)
from (
select grupa,
decode(sign(godine-19)+sign(31-godine),2,1,1,null,0,null) "20-30",
decode(sign(godine-32)+sign(41-godine),2,1,1,null,0,null) "31-40",
decode(sign(godine-42)+sign(51-godine),2,1,1,null,0,null) "41-50"
from ljudi
)
group by grupa
[/code:1]

Rezultat:
[code:1]
GRUPA 20-30 31-40 41-50 COUNT(*)
--------- --------- --------- --------- ---------
1 2 1 1 4
2 2 1 0 3
[/code:1]

Alat SQL*Plus, baza Oracle 8i
Ako ima nejasnoća, pitaj...

Ajd, poz & stay black! type;
 
Al ga opravi, svaka ti cast!

Nisam do sad imao prilike da upotrebljavam f-ju decode. Na brzaka sam pogledao i mislim da mi je jasna tvoja koncepcija. Kad su oba uslova zadovoljena Sign(+1 +1 = 2) dodeljujes vrednost 1, inace NULL
Cini mi se da bi u unutrasnjem SELECT-u onda mogao da skratis
[code:1]
decode(sign(godine-19)+sign(31-godine),2,1,1,null,0,null) "20-30"
[/code:1]
na
[code:1]
decode(sign(godine-19)+sign(31-godine),2,1,null) "20-30"
[/code:1]

i slicno.

Pretpostavljam da bi mogao i za one koji ne_zadovoljavaju da dodeljujes vrednost 0 umesto NULL, a onda u glavnom upitu koristis SUM funkciju umesto COUNT?

Ne znam kako ce moj ISQL da proguta ovu sintaksu (sa navodnicima), mozda cu tu morati da napravim minimalne korekcije. U svakom slucaju probacu kad stignem sa mojom realnom bazom ovako da resim.

U svakom slucaju, hvala na resenju:)
 
Navodnici stoje samo da bi upit bio sto jasniji, mozes da stavis sta hoces...
 
Ako imas jos koji problem, pitaj, volim da resavam probleme, mada ne obecavam ekspresan odgovor...
Obavezno javi da li je upit prosao i sa kakvim korekcijama, posto pretpostavljam da su neke stvari platform-specific.
Ekvivalent decode-u u Access-u je switch...
 
Vrh Dno