PostgreSQL ಆಂಟಿಪ್ಯಾಟರ್ನ್ಸ್: "ಒಂದೇ ಒಂದು ಇರಬೇಕು!"

SQL ನಲ್ಲಿ, ನೀವು "ಏನು" ಪಡೆಯಬೇಕೆಂದು ವಿವರಿಸುತ್ತೀರಿ, ಅದನ್ನು "ಹೇಗೆ" ಮಾಡಬಾರದು. ಆದ್ದರಿಂದ, SQL ಪ್ರಶ್ನೆಗಳನ್ನು "ಕೇಳಿದಂತೆಯೇ ಬರೆಯಲಾಗಿದೆ" ಎಂಬ ಶೈಲಿಯಲ್ಲಿ ಅಭಿವೃದ್ಧಿಪಡಿಸುವ ಸಮಸ್ಯೆಯು ಅದರ ಗೌರವದ ಸ್ಥಾನವನ್ನು ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ. SQL ನಲ್ಲಿ ಸ್ಥಿತಿಯ ಮೌಲ್ಯಮಾಪನದ ವಿಶಿಷ್ಟತೆಗಳು.

ಇಂದು, ಅತ್ಯಂತ ಸರಳವಾದ ಉದಾಹರಣೆಗಳನ್ನು ಬಳಸಿಕೊಂಡು, ಇದು ಬಳಸುವ ಸಂದರ್ಭದಲ್ಲಿ ಏನು ಕಾರಣವಾಗಬಹುದು ಎಂಬುದನ್ನು ನೋಡೋಣ GROUP/DISTINCT и LIMIT ಅವರೊಂದಿಗೆ.

ನೀವು ವಿನಂತಿಯಲ್ಲಿ ಬರೆದಿದ್ದರೆ ಅದು "ಮೊದಲು ಈ ಮಾತ್ರೆಗಳನ್ನು ಸಂಪರ್ಕಿಸಿ, ತದನಂತರ ಎಲ್ಲಾ ನಕಲುಗಳನ್ನು ಎಸೆಯಿರಿ, ಕೇವಲ ಒಂದು ಇರಬೇಕು ಪ್ರತಿ ಕೀಗೆ ಉದಾಹರಣೆ" - ಸಂಪರ್ಕವು ಅಗತ್ಯವಿಲ್ಲದಿದ್ದರೂ ಸಹ ಇದು ನಿಖರವಾಗಿ ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ.

ಮತ್ತು ಕೆಲವೊಮ್ಮೆ ನೀವು ಅದೃಷ್ಟವಂತರು ಮತ್ತು ಅದು "ಕೇವಲ ಕೆಲಸ ಮಾಡುತ್ತದೆ", ಕೆಲವೊಮ್ಮೆ ಇದು ಕಾರ್ಯಕ್ಷಮತೆಯ ಮೇಲೆ ಅಹಿತಕರ ಪರಿಣಾಮವನ್ನು ಬೀರುತ್ತದೆ, ಮತ್ತು ಕೆಲವೊಮ್ಮೆ ಇದು ಡೆವಲಪರ್ನ ದೃಷ್ಟಿಕೋನದಿಂದ ಸಂಪೂರ್ಣವಾಗಿ ಅನಿರೀಕ್ಷಿತ ಪರಿಣಾಮಗಳನ್ನು ನೀಡುತ್ತದೆ.

PostgreSQL ಆಂಟಿಪ್ಯಾಟರ್ನ್ಸ್: "ಒಂದೇ ಒಂದು ಇರಬೇಕು!"
ಒಳ್ಳೆಯದು, ಬಹುಶಃ ಅದ್ಭುತವಾಗಿಲ್ಲ, ಆದರೆ ...

"ಸ್ವೀಟ್ ಜೋಡಿ": ಸೇರಿಕೊಳ್ಳಿ + ಡಿಸ್ಟಿಂಕ್ಟ್

SELECT DISTINCT
  X.*
FROM
  X
JOIN
  Y
    ON Y.fk = X.pk
WHERE
  Y.bool_condition;

ಅವರಿಗೆ ಏನು ಬೇಕು ಎಂಬುದು ಹೇಗೆ ಸ್ಪಷ್ಟವಾಗುತ್ತದೆ ಅಂತಹ ದಾಖಲೆಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ X, ಇದಕ್ಕಾಗಿ Y ನಲ್ಲಿ ಪೂರೈಸಿದ ಸ್ಥಿತಿಯೊಂದಿಗೆ ಸಂಬಂಧಿಸಿವೆ. ಮೂಲಕ ಮನವಿ ಸಲ್ಲಿಸಿದರು JOIN - pk ಯ ಕೆಲವು ಮೌಲ್ಯಗಳನ್ನು ಹಲವಾರು ಬಾರಿ ಸ್ವೀಕರಿಸಲಾಗಿದೆ (ನಿಖರವಾಗಿ Y ನಲ್ಲಿ ಎಷ್ಟು ಸೂಕ್ತವಾದ ದಾಖಲೆಗಳು ಹೊರಹೊಮ್ಮಿವೆ). ತೆಗೆದುಹಾಕುವುದು ಹೇಗೆ? ಖಂಡಿತವಾಗಿಯೂ DISTINCT!

ಪ್ರತಿ ಎಕ್ಸ್-ರೆಕಾರ್ಡ್‌ಗೆ ನೂರಾರು ಸಂಬಂಧಿತ ವೈ-ರೆಕಾರ್ಡ್‌ಗಳು ಇದ್ದಾಗ ಇದು ವಿಶೇಷವಾಗಿ “ಆಹ್ಲಾದಕರ”, ಮತ್ತು ನಂತರ ನಕಲುಗಳನ್ನು ವೀರೋಚಿತವಾಗಿ ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ ...

PostgreSQL ಆಂಟಿಪ್ಯಾಟರ್ನ್ಸ್: "ಒಂದೇ ಒಂದು ಇರಬೇಕು!"

ಸರಿಪಡಿಸುವುದು ಹೇಗೆ? ಪ್ರಾರಂಭಿಸಲು, ಕಾರ್ಯವನ್ನು ಮಾರ್ಪಡಿಸಬಹುದು ಎಂದು ಅರಿತುಕೊಳ್ಳಿ "ಯಾವ ರೆಕಾರ್ಡ್‌ಗಳು X ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಿ, ಇದಕ್ಕಾಗಿ 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 ಆಂಟಿಪ್ಯಾಟರ್ನ್‌ಗಳು: ಅಪರೂಪದ ದಾಖಲೆಯು ಸೇರುವ ಮಧ್ಯಭಾಗವನ್ನು ತಲುಪುತ್ತದೆ".

"ಏಕೆ ಹೆಚ್ಚು ಪಾವತಿಸಿ": DISTINCT [ON] + 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

ಇದೇ ರೀತಿಯ ವಿಷಯಗಳು ವಿಭಿನ್ನವಾಗಿ ಸಂಭವಿಸುತ್ತವೆ ಶೂನ್ಯತೆಯ ತಪಾಸಣೆ ವಿನಂತಿಯು ಮುಂದುವರೆದಂತೆ ಲೇಬಲ್‌ಗಳು ಅಥವಾ CTEಗಳು:

...
CASE
  WHEN (
    SELECT
      count(*)
    FROM
      X
    LIMIT 1
  ) = 0 THEN ...

ಒಟ್ಟು ಕಾರ್ಯಗಳು (count/min/max/sum/...) ಸ್ಪಷ್ಟವಾಗಿ ನಿರ್ದಿಷ್ಟಪಡಿಸದೆಯೇ ಸಂಪೂರ್ಣ ಸೆಟ್‌ನಲ್ಲಿ ಯಶಸ್ವಿಯಾಗಿ ಕಾರ್ಯಗತಗೊಳಿಸಲಾಗುತ್ತದೆ GROUP BY. ಇಲ್ಲಿ ಮಾತ್ರ 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, ಮತ್ತು ಕೋಷ್ಟಕದಲ್ಲಿ ನೂರಾರು ಸಾವಿರ ದಾಖಲೆಗಳಿವೆ ...

ವ್ಯರ್ಥವಾಗಿ ದುಃಖಿಸದಿರಲು, ನಾವು ಪುನರಾವರ್ತಿತ ಪ್ರಶ್ನೆಯನ್ನು ಬಳಸುತ್ತೇವೆ PostgreSQL ವಿಕಿಯಿಂದ "DISTINCT for the Poor":

PostgreSQL ಆಂಟಿಪ್ಯಾಟರ್ನ್ಸ್: "ಒಂದೇ ಒಂದು ಇರಬೇಕು!"

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ