በ SQL ውስጥ "ምን" ማግኘት እንደሚፈልጉ ይገልጻሉ, "እንዴት እንደሚደረግ" ሳይሆን. ስለዚህ የSQL ጥያቄዎችን የማዳበር ችግር “እንደ ተጻፈው ነው” በሚለው ዘይቤ የክብር ቦታውን ይይዛል።
ዛሬ, እጅግ በጣም ቀላል ምሳሌዎችን በመጠቀም, ይህ በአጠቃቀም ሁኔታ ውስጥ ምን ሊያስከትል እንደሚችል እንይ GROUP/DISTINCT
и LIMIT
ከእነሱ ጋር.
አሁን, በጥያቄው ውስጥ ከጻፉ “መጀመሪያ እነዚህን ምልክቶች ያገናኙ እና ከዚያ ሁሉንም የተባዙትን ይጣሉ። አንድ ብቻ ይቀራል ለእያንዳንዱ ቁልፍ ቅዳ" - ግንኙነቱ ጨርሶ ባያስፈልግም እንኳን በትክክል የሚሰራው በዚህ መንገድ ነው።
እና አንዳንድ ጊዜ እድለኛ ነዎት እና "ልክ ይሰራል", አንዳንድ ጊዜ በአፈፃፀም ላይ ደስ የማይል ተጽእኖ ይኖረዋል, እና አንዳንድ ጊዜ ከገንቢው እይታ ሙሉ በሙሉ ያልተጠበቁ ውጤቶችን ይሰጣል.
ደህና ፣ ምናልባት ያን ያህል አስደናቂ ላይሆን ይችላል ፣ ግን…
“ጣፋጭ ባልና ሚስት”፡ ይቀላቀሉ + ልዩነት
SELECT DISTINCT
X.*
FROM
X
JOIN
Y
ON Y.fk = X.pk
WHERE
Y.bool_condition;
ምን እንደሚፈልጉ ግልጽ ይሆናል በ Y ውስጥ ከተሟላ ሁኔታ ጋር የሚዛመዱ መዝገቦች ያሉባቸውን መዝገቦች X ይምረጡ. በኩል ጥያቄ ጻፈ JOIN
- አንዳንድ pk እሴቶችን ብዙ ጊዜ አግኝቷል (በ Y ውስጥ ምን ያህል ተስማሚ ግቤቶች እንደታዩ በትክክል)። እንዴት ማስወገድ እንደሚቻል? በእርግጠኝነት DISTINCT
!
በተለይ ለእያንዳንዱ ኤክስ ሪከርድ ብዙ መቶ ተዛማጅ ዋይ መዛግብቶች ሲኖሩ እና ከዚያም ብዜቶቹ በጀግንነት ሲወገዱ "አስደሳች" ነው...
እንዴት ማስተካከል ይቻላል? ለመጀመር, ችግሩ ወደ ሊስተካከል የሚችል መሆኑን ይገንዘቡ "መዝገብ X ምረጥ ለዚህም በ Y ውስጥ ከተሟላ ሁኔታ ጋር የተያያዘ ቢያንስ አንድ" - ከሁሉም በላይ, ከ Y-መዝገብ እራሱ ምንም ነገር አያስፈልገንም.
EXISTS መክተት
SELECT
*
FROM
X
WHERE
EXISTS(
SELECT
NULL
FROM
Y
WHERE
fk = X.pk AND
bool_condition
LIMIT 1
);
አንዳንድ የPostgreSQL ስሪቶች በEXISTS ውስጥ የሚመጣውን የመጀመሪያ ግቤት ማግኘት በቂ እንደሆነ ይገነዘባሉ ፣ አዛውንቶች አያገኙም። ስለዚህ ሁልጊዜ መጠቆም እመርጣለሁ LIMIT 1
ውስጥ EXISTS
.
ከጎን ይቀላቀሉ
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;
ተመሳሳዩ አማራጭ, አስፈላጊ ከሆነ, ከተገኘው ተያያዥ የ Y-መዝገብ ላይ አንዳንድ መረጃዎችን ወዲያውኑ ለመመለስ ያስችላል. ተመሳሳይ አማራጭ በአንቀጹ ውስጥ ተብራርቷል
"PostgreSQL Antipatterns፡ ብርቅዬ ሪከርድ ወደ መቀላቀል መሃል ይደርሳል" .
"ለምን ተጨማሪ ይክፈሉ"፡ DISTINCT [በርቷል] + LIMIT 1
የእንደዚህ አይነት የጥያቄ ለውጦች ተጨማሪ ጥቅም በሚከተለው ሁኔታ አንድ ወይም ጥቂት ብቻ አስፈላጊ ከሆነ መዝገቦችን ፍለጋ በቀላሉ የመገደብ ችሎታ ነው።
SELECT DISTINCT ON(X.pk)
*
FROM
X
JOIN
Y
ON Y.fk = X.pk
LIMIT 1;
አሁን ጥያቄውን እናነባለን እና DBMS ምን ለማድረግ እንደታሰበ ለመረዳት እንሞክራለን፡
- ምልክቶችን በማገናኘት ላይ
- ልዩ በ X.pk
- ከቀሪዎቹ ግቤቶች አንዱን ይምረጡ
ታዲያ ምን አገኘህ? "አንድ ግቤት ብቻ" ልዩ ከሆኑት - እና ይህንን ልዩ ካልሆኑት ውስጥ ብንወስድ ውጤቱ በሆነ መንገድ ይቀየራል? ... "እና ምንም ልዩነት ከሌለ, ለምን የበለጠ ይከፍላሉ?"
SELECT
*
FROM
(
SELECT
*
FROM
X
-- сюда можно подсунуть подходящих условий
LIMIT 1 -- +1 Limit
) X
JOIN
Y
ON Y.fk = X.pk
LIMIT 1;
እና በትክክል ተመሳሳይ ርዕስ GROUP BY + LIMIT 1
.
"መጠየቅ አለብኝ"፡ ስውር GROUP + LIMIT
ተመሳሳይ ነገሮች በተለያየ መንገድ ይከሰታሉ ባዶ ያልሆኑ ቼኮች ጥያቄው እየገፋ ሲሄድ ምልክቶች ወይም CTEs፡-
...
CASE
WHEN (
SELECT
count(*)
FROM
X
LIMIT 1
) = 0 THEN ...
አጠቃላይ ተግባራት (count/min/max/sum/...
) ያለ ግልጽ መመሪያም ቢሆን በጠቅላላው ስብስብ ላይ በተሳካ ሁኔታ ይፈጸማሉ GROUP BY
. ጋር ብቻ LIMIT
በጣም ተግባቢ አይደሉም።
ገንቢው ማሰብ ይችላል። "እዚያ መዝገቦች ካሉ ከ LIMIT በላይ አያስፈልገኝም". ግን ያንን አታድርጉ! ምክንያቱም ለመሠረቱ የሚከተለው ነው-
- የሚፈልጉትን ይቁጠሩ በሁሉም መዝገቦች መሠረት
- የጠየቁትን ያህል መስመሮችን ይስጡ
በዒላማው ሁኔታ ላይ በመመስረት ከሚከተሉት ምትክ አንዱን ማድረግ ተገቢ ነው.
(count + LIMIT 1) = 0
ላይNOT EXISTS(LIMIT 1)
(count + LIMIT 1) > 0
ላይEXISTS(LIMIT 1)
count >= N
ላይ(SELECT count(*) FROM (... LIMIT N))
"በግራም ምን ያህል ይመዝናል"፡ DISTINCT + LIMIT
SELECT DISTINCT
pk
FROM
X
LIMIT $1
የዋህ ገንቢ ጥያቄው መፈጸሙን ያቆማል ብሎ በቅንነት ያምን ይሆናል። ከመጀመሪያዎቹ የተለያዩ ዋጋዎች ውስጥ 1 ዶላር እንዳገኘን.
አንዳንድ ጊዜ ወደፊት ይህ ለአዲስ መስቀለኛ መንገድ ምስጋና ይግባውና ሊሠራ ይችላል። ማውጫ ዝለል ቅኝት።, አተገባበሩ በአሁኑ ጊዜ እየተሰራ ነው, ግን ገና አይደለም.
ለአሁን መጀመሪያ ሁሉም መዝገቦች ተሰርስረው ይወሰዳሉ, ልዩ ናቸው, እና ከነሱ ብቻ የተጠየቀው መጠን ይመለሳል. በተለይ እንደዚህ አይነት ነገር ከፈለግን በጣም ያሳዝናል $ 1 = 4, እና በሰንጠረዡ ውስጥ በመቶ ሺዎች የሚቆጠሩ መዝገቦች አሉ ...
በከንቱ እንዳንዘን፣ ተደጋጋሚ ጥያቄን እንጠቀም
ምንጭ: hab.com