Использование CTE для отображения переходных отношений в данных - PullRequest
3 голосов
/ 19 марта 2019

Я работаю над археологической базой данных, которая включает пару таблиц, описывающих пространственные отношения между стратиграфическими единицами. Это довольно просто - юнит находится выше или ниже другого юнита. Для этого у меня есть таблица, в которой записаны unit_1, unit_2 и тип пространственной связи между ними (выше или ниже). Я также хочу создать представление, которое также записывает транзитивный аналог. Другими словами, если единица A выше единицы B, я также хочу временную строку, указывающую, что единица B ниже единицы A.

Вот так сейчас выглядит мой CTE. Я получаю сообщение об ошибке «ОШИБКА: отношение« matrix_cte »не существует», так что это, вероятно, не способ сделать это. Но идея здесь заключается в том, что когда отношение «выше» (то же самое, что и 1), команда INSERT должна добавить новую строку в таблицу, созданную, где две единицы поменялись местами, и отношение ниже (или 2) , Любая помощь с благодарностью, заранее спасибо.

WITH matrix_cte  (unit, related_unit, relationship)
AS (SELECT lookup_unit,
lookup_unit_2,
lookup_unit_relationship

FROM register_unit_matrix)
INSERT INTO matrix_cte(unit, related_unit, relationship)
SELECT lookup_unit_2, lookup_unit, 2
FROM (register_unit_matrix

INNER JOIN matrix_cte ON ((register_unit_matrix.lookup_unit = matrix_cte.unit)))
WHERE relationship = 1;

1 Ответ

3 голосов
/ 19 марта 2019

Вы не можете INSERT в CTE.CTE - это логическая таблица, это псевдоним набора результатов.Вы можете SELECT из CTE.Не совсем уверен, чего вы там добиваетесь.

ОШИБКА: отношение "matrix_cte" не существует

Это сообщение об ошибке означает, что вы можете INSERT только вотношения (таблицы).CTE - это не таблица, это не постоянный объект в базе данных, и в вашей базе данных нет таблицы с именем matrix_cte.


Чтобы сгенерировать все отношения, как прямые, так и обратные, вы можете UNION два набора результатов вместе.Если ваша исходная таблица имеет отношения только в одном направлении, тогда вы можете использовать UNION ALL, и запрос будет быстрее.Я имею в виду, если в исходной таблице никогда не бывает двух строк для одной и той же пары единиц:

unit1, unit2, 1
unit2, unit1, 2

, тогда вы можете использовать UNION ALL ниже.Если в исходной таблице могут быть такие дубликаты, вы должны использовать UNION для удаления дополнительных дубликатов.

-- all direct relationships as they are
SELECT 
    lookup_unit,
    lookup_unit_2,
    lookup_unit_relationship
FROM register_unit_matrix

UNION

-- inverse all relationships 
SELECT 
    lookup_unit_2,
    lookup_unit,
    CASE WHEN lookup_unit_relationship = 1 THEN 2 ELSE 1 END AS lookup_unit_relationship
FROM register_unit_matrix

Вы можете поместить этот запрос выше в представление или использовать как есть.

...