Sa SQL, inilalarawan mo ang "ano" na gusto mong makamit, hindi "kung paano" ito dapat isagawa. Samakatuwid, ang problema sa pagbuo ng mga query sa SQL sa estilo ng "tulad ng narinig ay kung paano ito isinulat" ay pumapalit sa lugar ng karangalan, kasama ang mga tampok ng pagkalkula ng mga kondisyon sa SQL.
Ngayon, gamit ang napakasimpleng mga halimbawa, tingnan natin kung ano ang maaaring humantong sa konteksto ng paggamit GROUP/DISTINCT ΠΈ LIMIT kasama nila.
Ngayon, kung sumulat ka sa kahilingan "Ikonekta muna ang mga palatandaang ito, at pagkatapos ay itapon ang lahat ng mga duplicate, dapat isa na lang ang natitira kopya para sa bawat susi" - ito ay eksakto kung paano ito gagana, kahit na ang koneksyon ay hindi kinakailangan sa lahat.
At kung minsan ikaw ay mapalad at ito ay "gumagana lamang", kung minsan ito ay may hindi kasiya-siyang epekto sa pagganap, at kung minsan ay nagbibigay ito ng mga epekto na ganap na hindi inaasahan mula sa punto ng view ng developer.
Well, marahil ay hindi masyadong kamangha-manghang, ngunit...
βSweet coupleβ: SUMALI + DISTINCT
SELECT DISTINCT
X.*
FROM
X
JOIN
Y
ON Y.fk = X.pk
WHERE
Y.bool_condition;
Magiging malinaw kung ano ang gusto nila piliin ang mga tala X kung saan mayroong mga tala sa Y na nauugnay sa natupad na kondisyon. Sumulat ng isang kahilingan sa pamamagitan ng JOIN β nakakuha ng ilang pk value ng ilang beses (eksaktong kung gaano karaming angkop na mga entry ang lumitaw sa Y). Paano tanggalin? tiyak DISTINCT!
Ito ay lalo na "kasiya-siya" kapag para sa bawat X-record mayroong ilang daang nauugnay na Y-record, at pagkatapos ay ang mga duplicate ay bayanihang tinanggal...
Paano ayusin? Upang magsimula sa, mapagtanto na ang problema ay maaaring baguhin sa "pumili ng mga tala X kung saan sa Y ay may KAHIT ISA na nauugnay sa natupad na kondisyon" - pagkatapos ng lahat, hindi namin kailangan ng anuman mula sa Y-record mismo.
Nested EXISTS
SELECT
*
FROM
X
WHERE
EXISTS(
SELECT
NULL
FROM
Y
WHERE
fk = X.pk AND
bool_condition
LIMIT 1
);
Ang ilang mga bersyon ng PostgreSQL ay nauunawaan na sa EXISTS ay sapat na upang mahanap ang unang entry na lalabas, ang mga nakatatanda ay hindi. Samakatuwid mas gusto kong palaging ipahiwatig LIMIT 1 sa loob 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;
βBakit magbayad ng higit paβ: DISTINCT [ON] + LIMIT 1
Ang isang karagdagang benepisyo ng naturang mga pagbabago sa query ay ang kakayahang madaling limitahan ang paghahanap para sa mga talaan kung kailangan lamang ng isa o ilan sa mga ito, tulad ng sa sumusunod na kaso:
SELECT DISTINCT ON(X.pk)
*
FROM
X
JOIN
Y
ON Y.fk = X.pk
LIMIT 1;
Ngayon ay binabasa namin ang kahilingan at sinisikap na maunawaan kung ano ang iminungkahing gawin ng DBMS:
pag-uugnay ng mga palatandaan
natatangi ng X.pk
mula sa natitirang mga entry, pumili ng isa
Kaya ano ang nakuha mo? "Isang entry lang" from the unique ones - and if we take this one of the non-unique ones, will the result change somehow?.. βAnd if there is no difference, why pay more?β
SELECT
*
FROM
(
SELECT
*
FROM
X
-- ΡΡΠ΄Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ΄ΡΡΠ½ΡΡΡ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΡΡΠΈΡ ΡΡΠ»ΠΎΠ²ΠΈΠΉ
LIMIT 1 -- +1 Limit
) X
JOIN
Y
ON Y.fk = X.pk
LIMIT 1;
At eksakto ang parehong paksa sa GROUP BY + LIMIT 1.
βMay itatanong lang akoβ: implicit GROUP + LIMIT
Ang mga katulad na bagay ay nangyayari sa iba't ibang paraan non-emptiness checks mga palatandaan o CTE habang umuusad ang kahilingan:
...
CASE
WHEN (
SELECT
count(*)
FROM
X
LIMIT 1
) = 0 THEN ...
Pinagsama-samang mga function (count/min/max/sum/...) ay matagumpay na naisakatuparan sa buong set, kahit na walang tahasang mga tagubilin GROUP BY. Kasama lamang LIMIT hindi sila masyadong palakaibigan.
Maaaring mag-isip ang developer "kung may mga talaan doon, kailangan ko ng hindi hihigit sa LIMIT". Ngunit huwag gawin iyon! Dahil para sa base ito ay:
bilangin ang gusto nila ayon sa lahat ng mga talaan
magbigay ng maraming linya hangga't hinihiling nila
Depende sa target na kundisyon, angkop na gawin ang isa sa mga sumusunod na pamalit:
(count + LIMIT 1) = 0saNOT EXISTS(LIMIT 1)
(count + LIMIT 1) > 0saEXISTS(LIMIT 1)
count >= Nsa(SELECT count(*) FROM (... LIMIT N))
"Magkano ang mabibitin sa gramo": DISTINCT + LIMIT
SELECT DISTINCT
pk
FROM
X
LIMIT $1
Ang isang walang muwang na developer ay maaaring taos-pusong naniniwala na ang kahilingan ay hihinto sa pagpapatupad. sa sandaling mahanap namin ang $1 ng unang magkakaibang mga halaga na makikita.
Sa hinaharap, maaari at gagana ito salamat sa isang bagong node Index Laktawan Scan, ang pagpapatupad nito ay kasalukuyang ginagawa, ngunit hindi pa.
Sa ngayon muna lahat ng mga tala ay kukunin, ay natatangi, at mula sa kanila lamang ibabalik ang hinihiling na halaga. Nakakalungkot lalo na kung may gusto tayo $ 1 = 4, at mayroong daan-daang libong mga tala sa talahanayan...