Soci (Soczó Zsolt) szakmai blogja

2015.01.20.

SQL fejtörő 5. megoldás

Filed under: Adatbázisok,SQL Server,Szakmai élet — Soczó Zsolt @ 18:56

Egyszerű csoportosítós példa.

A legkézenfekvőbb megoldás egy sima group by és min:

select E.Nev, Telefon = min(E.Telefon) from Ember E group by E.Nev

Ezt egy covering nc indexszel szépen fel lehet gyorsítani:

CREATE NONCLUSTERED INDEX [IX_1] ON [dbo].[Ember]
(
	[Nev] ASC
)
INCLUDE ([Telefon]) 

Egy másik megoldás már költségesebb, de helyes eredményt ad (a komment szerzője szerintem ismerte az elsőt, csak valami trükkösebb megoldást akart adni):

select *
from Ember e1
where not exists (
select *
from Ember e2
where e1.Nev = e2.Nev
and e1.Telefon > e2.Telefon
)

Ennek logikája már körülményesebb, kérem azokat a sorokat, amelyekhez nem létezik olyan sor, aminek ugyanaz a neve, de kisebb a telefonszáma. Ezt csak joinnal tudja megoldani a szerver, jelentősen nagyobb költséggel.

Egy jelentősen más logikájú megoldás is érkezett:

;WITH Data AS
(
	SELECT Nev, Telefon, ROW_NUMBER() OVER (PARTITION BY Nev ORDER BY Telefon) AS RowNumber
	FROM Ember
)
SELECT Nev, Telefon
FROM Data
WHERE RowNumber = 1

Felsorszámozzuk a sorokat a Telefon szerint rendezve, partícionálva a Nev alapján, majd ebből a halmazból kiszedjük azokat a sorokat, amelyek sorszáma 1. Minden Nev-hez 1 ilyen lesz, értelemszerűen.
Ez a megoldás nem szereti az előbbi indexünket. Ahhoz, hogy ez is gyors legyen, a Telefon oszlopot is bele kell rakni az index kulcsai közé:

CREATE NONCLUSTERED INDEX [IX_1] ON [dbo].[Ember]
(
	[Nev] ASC,
	[Telefon] ASC
)

Így a group by-os és ezen megoldás költsége már azonos lesz, bár a tervük nem. Ez esetben sok sor esetén lehetne eldönteni, van-e perf különbség a két megoldás között, akinek van erre ideje, érdekelne az eredménye. Mondjuk 10 millió sorra. Érzésre nem lesz, de cáfoljatok meg, konkrét terveket mutatva.

Köszönöm mindenkinek a megoldásokat, és külön köszönöm Molnár Csabának, hogy a nem nyilvánvaló megoldást is megmutatta.

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress