Novo

Forum kao aplikacija na telefonu

Dodajte forum na početni ekran i koristite ga kao aplikaciju, sa menijem na dnu ekrana.

  • 16 odgovora
  • 6.953 pregleda

Najnovija ↓

Re: poslednji zapis uz pomoc join-a? 20.01.2008. u 20:54 · pre 228 meseci #2
Code:

SELECT MAX(Date) AS Poslednji, username 
FROM Tabela1 INNER JOIN Tabela2 ON Tabela1.ID = Tabela2.ID
GROUP BY username
Re: poslednji zapis uz pomoc join-a? 20.01.2008. u 21:47 · pre 228 meseci #3
ovaj kod:

Code:
SELECT u_id,date
FROM tabela1 where u_id in (19,160)
ORDER BY date desc 
LIMIT 10


ispisuje:

Code:
 u_id |    date    
------+------------
  160 | 2008-01-14
   19 | 2008-01-14
   19 | 2008-01-14
   19 | 2008-01-14
  160 | 2008-01-14
  160 | 2008-01-14
  160 | 2008-01-14
   19 | 2008-01-14
   19 | 2008-01-14
   19 | 2008-01-14


i gotov je u sekundi.

ovo sto si napisao traje previse dugo cak i kada dodam uslov

Code:
...
WHERE id in (19,160)


imas li jos neki predlog?
Re: poslednji zapis uz pomoc join-a? 20.01.2008. u 22:33 · pre 228 meseci #5
kako da spajanjem dve tabele dobijem samo jedan zapis (po id-u), a ne kombinaciju koja se dobija klasicnim JOIN pristupom.

da probam ovako: u jednoj tabeli je id kupca i datum kupovine.
u drugoj tabeli je id kupca i ime kupca.

kako dobiti id kupca, ime kupca i datum poslednje kupovine?
Re: poslednji zapis uz pomoc join-a? 20.01.2008. u 23:47 · pre 228 meseci #6
Ako sam dobro shavtio, mislis na ovo?


Code:


SELECT top 1 u_id,date
FROM tabela1 where u_id in (19,160)
ORDER BY date desc 
Re: poslednji zapis uz pomoc join-a? 25.01.2010. u 13:37 · pre 204 meseca #8
Koliko sam shvatio, niko nije odgovorio na ovo, a sada i meni treba :-(

Imam jednu tabelu sa ID-om, a drugu tabelu sa njegovim atributima, vise atributa za jedan ID...
T1:
ID,
Naziv,
...


T2:
ID,
Atribut
VremeUnosa


Treba mi da izlistam sve iz T1 sa poslednjim unesenim atributom
?
Potpis
Uhvatili ste me nespremnog
Re: poslednji zapis uz pomoc join-a? 25.01.2010. u 14:32 · pre 204 meseca #10
Nije dobro, zapravo dobio si isto sto i inner join.

Znam sta vas zulja ;) Lako bi resili agregacijom samo da nije tog atribut polja koje se razlikuje pa totalno unisti group by ;)
Resenje je da prvo napravite agregaciju datuma samo po ID, bez ostalih polja i onda to joinujete sa T2 po tom virtuelnom kompozitnom kljucu.

Code:
select T2.*
from T2
inner join (select ID, MAX(DatumUnosa) as MaxDT
            from T2
            group by ID
        ) T2L on T2L.ID = T2.ID and T2L.MaxDT = T2.DatumUnosa


ovo ce vratiti tabelu sa ID i poslednji uneseni atribut i vreme unosa. To sad mozete da okacite kao view radi preglednosti (pa se on joinuje na T1) a moze i da se uradi inner join na T1 direktno:

Code:
select T1.*, T2N.*
from T1
inner join (select T2.*
            from T2
                    inner join (select ID, MAX(DatumUnosa) as MaxDT
                    from T2
                    group by ID) 
                    T2L on T2L.ID = T2.ID and T2L.MaxDT = T2.DatumUnosa
            ) T2N on T2N.ID = T1.ID


Mozda postoji i malo optimalnije resenje, ali ni ovo nije lose, ako postoji desc index na datumu i ID je PK sve se resava sa dva clustered scan-a. Dupli rezultati mogu da se pojave samo ako ima dva atributa sa istim datetime, ali onda i mora da se definise koji je vazniji od ta dva da bi se rafinisalo resenje.


Potpis
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog
naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji
je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan,
sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv - Z.Đinđić
Re: poslednji zapis uz pomoc join-a? 26.01.2010. u 11:52 · pre 204 meseca #13
Code:

 SELECT  t1.*, a.* FROM  t1 
 OUTER APPLY (SELECT TOP (1) * FROM  t2 WHERE t2.id=t1.id ORDER BY t2.vreme DESC) a


gde je T1 glavna tabela, a T2 tabela atributa

izraz unutar OUTER APPLY evaluira se za svaki red glavne tabele (predaje mu se argument ID) i ponasa se slicno subselectu, s tim sto je neuporedivo mocniji. Subselect vraca iskljucivo skalarnu vrednost, dok je ovde moguce vratiti virtuelnu tabelu (vise kolona i vise redova).

Potpis
Sad šta je tu je. A možda će da dođe i ova tvoja tetka iz Bosanske Krupe.
Re: poslednji zapis uz pomoc join-a? 26.01.2010. u 12:38 · pre 204 meseca #14
Odlicno resenje, bez agregacije. Cak je i brze 30% od onog sto sam okacio, pod uslovom da postoji desc indeks na vremeunosa, u suprotnom je 4 put sporiji (zbog sorta).

Potpis
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog
naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji
je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan,
sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv - Z.Đinđić
Re: poslednji zapis uz pomoc join-a? 26.01.2010. u 13:13 · pre 204 meseca #15
Jeste, resenje je elegantno i performantno dok tabela ne postane prevelika. Onda troskovi, inace elegantnog Nested Lopps operatora postaju neprijatni ili cak nepodnosljivi. U tom slucaju vise se isplati uraditi JOIN, pa pokupiti samo ono sto nam treba. Optimizer ce u vezi JOIN-a izabrati optimalni pristup za velike table, sto u slucaju APPLY operatora nazalost nece - njemu je tu velicina tabele irelevantna. Ovo bi moglo da bude resenja za large table:

Code:

WITH cte as
(
SELECT t1.id, t1.naziv, t2.atribut, t2.vreme, ROW_NUMBER() OVER(PARTITION BY t2.id ORDER BY t2.vreme DESC) as rn 
FROM  t1
LEFT OUTER JOIN  t2
    ON t1.id = t2.id 
)
SELECT * FROM cte WHERE rn=1


Na velikoj tabli treba mu mnogo manje logical read-ova, nego resenju sa APPLY.

Potpis
Sad šta je tu je. A možda će da dođe i ova tvoja tetka iz Bosanske Krupe.
Re: poslednji zapis uz pomoc join-a? 26.01.2010. u 14:28 · pre 204 meseca #16
Hm, ne vidim to. U ovom slucaju imas obavezan sort tek nakon outer join-a, sto znaci da query engine uvek mora da formira pun outer join dataset sa max t1+t2 redova da bi primenio sort i projektovao ROW_NUMBER().
Sa druge strane outer apply resenje koje si dao ce (uz postojanje desc indeksa na vremenu) uvek raditi sa t2 redova bez ijednog sorta i bez ijednog table scan-a, sve ce cupati iz indeksa. U principu oba se svedu na left outer operaciju samo u row_number() slucaju uvek vise redova dolazi iz T2 seta a where uslov ne moze da se primeni pre outer-joina jer je na projektovanom polju i samim tim ne vidim prostor za query optimizera.

Linq2Sql recimo dosta koristi tu taktiku sa ROW_NUMBER() u Take(int) operacijama jer rn omogicava sve komparativne operacije (<, >, itd), ali to mi ne deluje nikako optimalno vec vise apstraktno i univerzalno.
Potpis
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog
naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji
je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan,
sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv - Z.Đinđić
Re: poslednji zapis uz pomoc join-a? 02.02.2010. u 09:08 · pre 203 meseca #17
Izvinjavam se na zakasnelom odgovoru...

ROW_NUMBER() resenje je performantnije kada je glavna tabela veoma velika. Uz odgovarajuce indekse optimizer se za ovo resenje generisati plan sa lepim Merge Join operatorom, pracenim ne tako lepim Sort operatorom. U ovom slucaju, kao sto si ti napomenuo, Sort je najveci konzument vremena i resursa. U zavisnosti od velicine tabele atributa moze da bude od koristi da se Sort operator prebaci sa leve strane Merge Join-a (da se najpre prvo sortira druga tabel, pa tek onda joinuje).

CROSS APPLY pristup je fiksan - za svaki red iz glavne tabele potrebne su 3 ili 4 strane iz tabele atributa. resenje odlicno skalira drugu tabelu, ranjivo je, medjutim, na velicinu glavne tabele. Ako u glavnoj tabli imamo 1M redova onda ovo resenje potrebuje 3-4M logical readova.

Dakle, u ovoj trci (ROW_NUMBER resenje vs. CROSS APPLY sa 1M redova u glavnoj tabli iliti Sort vs. Nested Loops) pobednik je ROW_NUMBER() do izvesnog broja redova u drugoj tabli (recimo 1.5 M). Sto je broj redova u drugoj tabli veci, vece su sanse da drugo resenje pobedi. Imao sam u praksi takav primer i resenjem sa ROW_NUMBER() uspeli smo da poboljsamo performanse za nekih 15-20% (SSMS ce poredeci ova dva plana sugerisati da poboljsanje treba da bude preko 50%, realno je, ipak, 15-tak %).

Izvinjavam se svim zbog sturog odgovora, @mmix nadam se da sam barem delimicno odgovorio na voje pitanje. Takodje se nadam da ce okolnosti dozvoliti da u narednih nekoliko dana napisem detaljan clanak o ovom problemu, sa kompletnim test skript rutinama.

Pozdrav,
M.
Potpis
Sad šta je tu je. A možda će da dođe i ova tvoja tetka iz Bosanske Krupe.
Prijavite se da biste odgovorili u ovoj temi.PrijavaRegistracija

Premeštanje teme