2016-04-03 3 views
3

Может ли кто-нибудь объяснить мне, как именно этот SQL-запрос работает точно?Как работает этот рекурсивный SQL CTE?

WITH recursive n(n) AS (
    SELECT 2 n 
    UNION ALL 
    SELECT n+1 FROM n WHERE n<1000 
) 
SELECT a.n 
FROM n a 
    LEFT JOIN n b 
    ON b.n < sqrt(a.n) 
GROUP BY a.n 
HAVING a.n=2 OR MIN(a.n % b.n) > 0; 

Это произведет следующее в POSTGRESQL:

n 
==== 
251 
887 
601 
647 
577 
... 
9 
(177 rows) 

Мое понимание линию за линией пробоя:

SELECT 2 n - выбрать номер 2, как п [анкерного элемента of CTE]

UNION ALL - объединить с рекурсивным компонентом n + 1 от n < 1000, поэтому отобразить все номера от 2 до 10 00

SELECT a.n FROM n a - запустить приведенный выше запрос [рекурсивный член КТР]

LEFT JOIN n b - левый присоединиться номера 2-1000 со вторым набором чисел

ON b.n < sqrt(a.n) - где второй набор чисел меньше квадратного корня из первого столбца чисел?

GROUP BY a.n - отображать только первый столбец чисел

HAVING a.n=2 OR MIN(a.n. % b.n) > 0 - ... где А = 2 или минимум А по модулю B больше 0?

Это глупый запрос, но любая помощь в расшифровке будет оценена по достоинству.

+0

Я думаю, что целью здесь является генерация простых чисел менее 1000. Однако результаты, похоже, не подтверждают, что, поскольку вы получаете 25,49 и т. Д. –

+0

внимательно изучая результаты, я думаю, что ваш запрос генерирует все простые числа и их квадраты меньше 1000. Но вы должны добавить еще одно условие в предложение 'have',' HAVING an = 2 ИЛИ an = 3 ИЛИ MIN (a% bn)> 0', чтобы включить 3 в результаты. –

ответ

4

Вашего запроса, если правильно фиксирован, генерирует список простых чисел ниже 1000:

WITH recursive n(n) AS (
    SELECT 2 n 
    UNION ALL 
    SELECT n+1 FROM n WHERE n<1000 
) 
SELECT a.n 
FROM n a 
    LEFT JOIN n b 
    ON b.n <= sqrt(a.n)      -- Fix #1 
GROUP BY a.n 
HAVING a.n=2 OR a.n=3 OR MIN(a.n % b.n) > 0 -- Fix #2 
ORDER BY a.n ASC 

Demo.

Объяснения довольно прост: рекурсивная часть запроса просто способ, чтобы дать вам список номеров от 2, включительно, до 1000, эксклюзивный. Вы можете заменить рекурсивное предложение фактической таблицей, заполненной последовательными целыми числами.

Эти номера затем передаются в часть запроса, не относящейся к CTE, и соединяются с самим собой по условию b.n < sqrt(a.n). Сторона a представляет собой простые числа кандидатов; сторона b представляет кандидаты-делители.

В этой статье есть первая ошибка: < необходимо заменить на <=, иначе квадратные корни простых квадратов будут включены в выход.

Группа GROUP BY объединяет потенциальные простые числа с делителями-кандидатами в одну группу. HAVING опускает все с одним или несколькими дивизорами-кандидатами, делящими кандидат простым равномерно, то есть где MIN(a.n % b.n) равно нулю.

Здесь вам понадобится второе исправление, потому что квадратный корень из 3, простое число, меньше 2, наименьшего кандидата-кандидата в списке. Следовательно, 3 заканчивается без каких-либо кандидатских дивизоров и выкидывается в HAVING; вам нужно добавить OR a.n=3, чтобы сохранить его.

+0

Удивительный! благодаря – OrdinaryHuman

Смежные вопросы