Що означає [ВІД x, y] у Postgres?


12

Я тільки починаю з Postgres. Читаючи цей документ, я натрапив на цей запит:

SELECT title, ts_rank_cd(textsearch, query) AS rank
FROM apod, to_tsquery('neutrino|(dark & matter)') query
WHERE query @@ textsearch
ORDER BY rank DESC
LIMIT 10;

Я можу зрозуміти все , що в цьому запиті, за винятком того, для цього: FROM apod, ....

Що це ,означає? Я звик приєднуватися, але не до декількох FROMвисловлювань, розділених комою.

Я шукав безрезультатно мережу. Подивившись на це і подумавши, мені здається, що він оголошує змінну під назвою запит, щоб вона могла використовувати її кілька разів. Але якщо це правда, яке це стосується FROM?

Відповіді:


10

Це створює неявне CROSS JOIN. Це синтаксис SQL-89.

Тут я використовую values(1)і values(2)створюю пседу-таблиці (таблиці значень) лише для прикладів. Річ після них t(x), і g(y)називається ВІД-Псевдонімом, символ всередині дужок є псевдонімом стовпця ( xі yвідповідно). Ви можете так само легко створити таблицю для перевірки цього.

SELECT *
FROM (values(1)) AS t(x), (values(2)) AS g(y)

Ось як би ви це написали зараз.

SELECT *
FROM (values(1)) AS t(x)
CROSS JOIN (values(2)) AS g(y);

Звідти ви можете зробити це неявним INNER JOINшляхом додавання умовного.

SELECT *
FROM (values(1)) AS t(x)
CROSS JOIN (values(1)) AS g(z)
WHERE x = z;

Або явний і новіший INNER JOINсинтаксис,

SELECT *
FROM (values(1)) AS t(x)
INNER JOIN (values(1)) AS g(z)
  ON ( x = z );

Отже, у вашому прикладі ..

FROM apod, to_tsquery('neutrino|(dark & matter)') query

Це по суті те саме, що і новіший синтаксис,

FROM apod
CROSS JOIN to_tsquery('neutrino|(dark & matter)') AS query

що насправді те саме, в цьому випадку, тому що to_tsquery()повертає рядок, а не набір як,

SELECT title, ts_rank_cd(
  textsearch,
  to_tsquery('neutrino|(dark & matter)')
) AS rank
FROM apod
WHERE to_tsquery('neutrino|(dark & matter)') @@ textsearch
ORDER BY rank DESC
LIMIT 10;

Однак вищезазначене може потенційно спричинити to_tsquery('neutrino|(dark & matter)')виникнення двічі, але в цьому випадку це не так - to_tsqueryпозначається як СТАБІЛЬНА (перевірена \dfS+ to_tsquery).

STABLEвказує на те, що функція не може змінювати базу даних, і що в межах однієї сканування таблиці вона послідовно повертає той самий результат для тих же значень аргументу, але що його результат може змінюватися в операторах SQL. Це відповідний вибір для функцій, результати яких залежать від пошуку в базі даних, змінних параметрів (таких як поточний часовий пояс) тощо. (Недоцільно ПІСЛЯ тригерів, які бажають запитувати рядки, змінені поточною командою.) Також зауважте, що Сімейство функцій current_timestamp кваліфікується як стабільне, оскільки їх значення не змінюються в межах транзакції.

Для більш повного порівняння відмінностей між SQL-89 та SQL-92 дивіться також мою відповідь тут


Дуже дякую. Я тільки починаю з SQL. Це має сенс ,бути перехресним з'єднанням, оскільки це лише декартовий продукт, і порівняння тут не береться. Чи можете ви просто відповісти на ще одне запитання? що t(x)в (values(1)) AS t(x)???
andrerpena

@andrerpena оновлено.
Еван Керролл

1
ти найкращий. Кришталево зрозуміле пояснення. Дякую тонну.
andrerpena

Ніколи не чув термін "Псевдонім" для псевдоніма таблиці . to_tsquery()повертає значення не рядок . І тільки тому , що функція визначена STABLE, це не означає , планувальник запитів буде уникнути повторної оцінки. Це може .
Ервін Брандстеттер

12

У посібнику є детальне пояснення для коми у FROMсписку в розділі Табличні вирази :

FROMПункт отримує таблицю з однієї або декількох інших таблиць , наведених в розділених комами довідкової таблиці списку.

FROM table_reference [, table_reference [, ...]]

Посилання на таблицю може бути назвою таблиці (можливо, відповідним схемою) або похідною таблицею, такою як підзапит, JOINконструкція або складні комбінації. Якщо в FROMпункті вказано більше одного посилання на таблицю , таблиці перетинаються між собою (тобто декартовий добуток їх рядків формується; див. Нижче).

Той факт, що посилання на таблицю, розділені комами, були визначені в попередній версії стандарту SQL, ніж явний JOINсинтаксис, не робить кому неправильною або застарілою. Використовуйте явний синтаксис приєднання, де це технічно необхідно (див. Нижче) або там, де він робить текст запиту зрозумілішим.

Посібник знову:

FROM T1 CROSS JOIN T2еквівалентний FROM T1 INNER JOIN T2 ON TRUE (див. нижче). Це також рівнозначно FROM T1, T2.

Але "еквівалент" не означає тотожне . Існує тонка різниця, як зазначає керівництво :

Примітка.
Ця остання еквівалентність не відповідає точно, коли з'являється більше двох таблиць, тому що JOINзв'язується більш щільно, ніж кома. Наприклад, FROM T1 CROSS JOIN T2 INNER JOIN T3 ON conditionце не те саме, що FROM T1, T2 INNER JOIN T3 ON conditionтому, що на conditionпосилання може посилатися T1в першому випадку, але не в другому.

Це пов'язане питання демонструє актуальність різниці:

В основному, ваше спостереження цілком вірно:

мені здається, що він оголошує змінну під назвою запит, щоб вона могла використовувати її кілька разів.

Будь-яка функція може використовуватися як "таблична функція" у FROMсписку. А параметри функції можуть посилати стовпці з усіх таблиць зліва від функції, оскільки позначення:

FROM apod, to_tsquery('neutrino|(dark & matter)') query

дійсно рівнозначно:

FROM apod CROSS JOIN LATERAL to_tsquery('neutrino|(dark & matter)') AS query

Посібник по запитам LATERAL:

Функціям таблиці, що з'являються у, FROMтакож може передувати ключове слово LATERAL, але для функцій ключове слово необов'язково ; Аргументи функції можуть містити посилання на стовпці, надані попередніми пунктами FROM в будь-якому випадку.

Сміливий акцент мій.

Ключове словоAS є обов'язковим шуму перед тим таблиці псевдонімів (на відміну від псевдонімів стовпців , де рекомендується не пропустити , ASщоб уникнути можливих неоднозначностей). Відповідна відповідь:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.