SQLis kirjeldad sa, âmidaâ soovid saada, mitte âkuidasâ see peaks toimuma. SeetĂ”ttu on SQL-pĂ€ringute koostamine stiilis ânagu kĂ”lab, nii kirjutatakseâ oma kohal. .
TĂ€na vaatame ĂŒli lihtsate nĂ€idete kaudu, kuhu see vĂ”ib viia seoses GROUP/DISTINCT ja LIMIT koos nendega.
Kui sa oled pĂ€ringus kirjutanud âkĂ”igepealt ĂŒhenda need tabelid ja seejĂ€rel eemalda kĂ”ik dubleed, peab alles jÀÀma ainult ĂŒks eksemplar iga vĂ”tme kohtaâ â just nii see töötabki, isegi kui liitmine polnud ĂŒldse vajalik.
Ja mĂ”nikord on Ă”nne ja see âlihtsalt töötabâ, mĂ”nikord â mĂ”jutab see negatiivselt jĂ”udlust, ja mĂ”nikord annab see arendaja vaatenurgast tĂ€iesti ootamatuid efekte.

No, vĂ”ib-olla mitte nii dramaatiliselt, agaâŠ
âMagus paarâ: JOIN + DISTINCT
SELECT DISTINCT
X.*
FROM
X
JOIN
Y
ON Y.fk = X.pk
WHERE
Y.bool_condition; Kuidas oleks mĂ”istlik, et sooviti valida sellised kirjed X, mille puhul Y-st on seotud tĂ€idetava tingimusega. Kirjutasid pĂ€ringu lĂ€bi JOIN â saadi mĂ”ned pk vÀÀrtused mitu korda (tĂ€pselt nii palju kui sobivaid kirjeid Y osutus). Kuidas eemaldada? Loomulikult. DISTINCT!
Eriti "rÔÔmustab", kui iga X-kirje kohta leidub mitusada seotud Y-kirjet, ja siis kangelaslikult eemaldatakse duplikaadidâŠ

Kuidas parandada? Alustuseks tunnistada, et ĂŒlesannet saab muuta jĂ€rgmistele. âvalida sellised X-kirjed, mille Y-s on KUIDAGI ĂKS seotud tingimusegaâ â sest Y-kirjast pole meile midagi vajalik.
Sisemine EXISTS
SELECT
*
FROM
X
WHERE
EXISTS(
SELECT
NULL
FROM
Y
WHERE
fk = X.pk AND
bool_condition
LIMIT 1
); MĂ”ned PostgreSQL versioonid mĂ”istavad, et EXISTS-is piisab esimese leidmise kirjega, vanemad â mitte. SeetĂ”ttu eelistan alati nĂ€idata LIMIT 1 sisemine EXISTS.
LATERAL JOIN
SELECT
X.*
FROM
X
, LATERAL (
SELECT
Y.*
FROM
Y
WHERE
fk = X.pk AND
bool_condition
LIMIT 1
) Y
WHERE
Y IS DISTINCT FROM NULL;Sama variant vÔimaldab vajadusel kohe tagasi tuua ka mingisuguseid andmeid leitud seosest Y-kirjest. Sarnast varianti kÀsitleti artiklis .
âMiks maksta rohkemâ: DISTINCT [ON] + LIMIT 1
Seda tĂŒĂŒpi pĂ€ringu ĂŒlemineku tĂ€iendav eelis on vĂ”imalus hĂ”lpsasti piirata salvestuste lĂ€bivaatamist, kui on vaja ainult ĂŒhte vĂ”i mitut neist, nagu jĂ€rgmisel juhul:
SELECT DISTINCT ON(X.pk)
*
FROM
X
JOIN
Y
ON Y.fk = X.pk
LIMIT 1;NĂŒĂŒd loeme pĂ€ringu ja pĂŒĂŒame aru saada, mida andmebaasi haldussĂŒsteem pakub:
- seome tabelid
- teeme X.pk alusel unikaalseks
- valime jÀÀkidest mingi ĂŒhe
Nii et mida me saime? âMingi ĂŒks salvestusâ unikaalsetest â aga kui vĂ”tta see ĂŒks mitteunikaalsetest, kas tulemus muutub kuidagi?⊠âAga kui vahet pole, miks maksma rohkem?â
SELECT
*
FROM
(
SELECT
*
FROM
X
-- siia saab sobivaid tingimusi lisada
LIMIT 1 -- +1 Limiteerimine
) X
JOIN
Y
ON Y.fk = X.pk
LIMIT 1;
Ja tÀpselt sama teema GROUP BY + LIMIT 1.
âMul on ainult kĂŒsidaâ: varjatud GROUP + LIMIT
Sarnaseid asju kohtab erinevate tĂŒhjuse kontrollide tabeli vĂ”i CTE lĂ€bimisel pĂ€ringu kĂ€igus:
...
CASE
WHEN (
SELECT
count(*)
FROM
X
LIMIT 1
) = 0 THEN ... Agregeerimisfunktsioonid (count/min/max/sum/...) töötavad edukalt kogu kogumi peal, isegi ilma selge viiteta GROUP BY. Ainult sellega on LIMIT nad pÀris hÀsti sÔbrad.
Arendaja vÔib arvata «kui seal on kirjed, siis mul ei tohi olla rohkem kui LIMIT». Aga nii ei tohi teha! Sest andmebaasi jaoks on see:
- arvuta, mida nad soovivad kÔigi rekordite kohta
- anna tagasi nii palju ridu, kui palutakse
SĂ”ltuvalt sihttingimustest on siin kohane teha ĂŒks asendusi:
(count + LIMIT 1) = 0jÀrgnevagaNOT EXISTS(LIMIT 1)(count + LIMIT 1) > 0jÀrgnevagaEXISTS(LIMIT 1)count >= NjÀrgnevaga(SELECT count(*) FROM (... LIMIT N))
«Mitu grammi kaaluda»: DISTINCT + LIMIT
SELECT DISTINCT
pk
FROM
X
LIMIT $1Naivne arendaja vÔib siiralt arvata, et pÀringu tÀitmine peatub, niipea kui leiame $1 esimestest erinevatest vÀÀrtustest.
Kord tulevikus vÔib see tÔesti toimida uue sÔlme tÔttu Index Skip Scan, mille rakendamine on praegu töös, aga praegu - ei ole.
Esialgu kĂ”ik kirjed on vĂ€lja tĂ”mmatud, unikaalsed, ja ainult neist tagastatakse, kui palju palutakse. Eriti kurb on, kui tahtsime midagi sarnast $1 = 4, aga tabelis on â sadu tuhandeidâŠ
Et mitte asjatult kurvastada, kasutame rekursiivset pÀringut :

Allikas: habr.com
