С этими «от» и «до» отношения быть двунаправленным (вы нуждаясь пройти в обоих направлениях), там просто нет просто заявление, чтобы сделать это в MySQL. Для того, чтобы получить все значения узлов в одном наборе результатов возвращенного в одном столбце, ближайший я могу прийти к избежанию операции UNION является:
SELECT CASE
WHEN t.i = 1 THEN t.dnode
WHEN t.i = 2 AND t.dnode = c.fromnode THEN c.tonode
WHEN t.i = 2 AND t.dnode = c.tonode THEN c.fromnode
ELSE NULL
END AS node
FROM (SELECT d.i
, m.root
, CASE WHEN m.root = n.fromnode THEN n.tonode ELSE n.fromnode END AS dnode
FROM (SELECT 'node1' AS root) m
CROSS
JOIN (SELECT 1 AS i UNION ALL SELECT 2) d
LEFT
JOIN conn n ON m.root IN (n.fromnode,n.tonode)
) t
LEFT
JOIN conn c
ON t.i = 2 AND t.dnode IN (c.fromnode,c.tonode)
GROUP BY node
ORDER BY node
Я не знаю, если я даже буду способный распаковать его, но я попробую. Чтобы избежать необходимости указывать корневой узел «node1» несколько раз, я использую подзапрос, чтобы вернуть его.
(SELECT 'node1' AS root) m
Потому что мы будем «два уровня глубины», мне нужно два набора узлов, поэтому я создать декартово произведение, чтобы удвоить количество строк У меня есть, и я собираюсь маркировать их 1 для первого уровня и 2 для второго уровня.
CROSS
JOIN (SELECT 1 AS i UNION ALL SELECT 2) d
С этим, я готов присоединиться к conn
столу, и я хочу все строки, которые имеют либо Fromnode или значение tonode, соответствующий корневой узел.
LEFT
JOIN conn n ON m.root IN (n.fromnode,n.tonode)
С этой результирующем я хочу «флип» на Fromnode и tonode на некоторых из этих строк так, что мы в основном всегда есть «корень» узел на одной стороне. Я делаю это с помощью выражения CASE, что тесты, которые сторона соответствует корню:
CASE WHEN m.root = n.fromnode THEN n.tonode ELSE n.fromnode END AS dnode
Так что теперь я обернуть эту ResultSet как вид рядные псевдонимами t
. Этот подзапрос может работать отдельно, чтобы увидеть, что мы возвращаемся, что мы ожидаем:
SELECT d.i
, m.root
, CASE WHEN m.root = n.fromnode THEN n.tonode ELSE n.fromnode END AS dnode
FROM (SELECT 'node1' AS root) m
CROSS
JOIN (SELECT 1 AS i UNION ALL SELECT 2) d
LEFT
JOIN conn n ON m.root IN (n.fromnode,n.tonode)
Нам нужно вернуть, что значение «уровень» (d.i
мы получили ранее, нам нужно это на следующем этапе, когда мы снова присоединиться к столу Конн, чтобы пройти на следующий уровень, и мне нужно только присоединиться те строки, где мы будем смотреть на втором уровне.
LEFT
JOIN conn c
ON t.i = 2 AND t.dnode IN (c.fromnode,c.tonode)
и опять же, я не забочусь, какая сторона узел включен, на данный момент мне просто нужно выполнить матч.
На этом этапе вы можете запустить весь запрос и вытащить t.*, c.*
, чтобы увидеть, что у нас есть, но я собираюсь пропустить эту часть и перейти прямо к «магии».
На этом этапе мы можем использовать выражение CASE для «выделения» нужного значения узла из этого беспорядка.
Если значение уровня (к сожалению, обозначено i
), равно 1, то мы смотрим на первый уровень, поэтому нам просто нужно получить значение «nodeX», которое было на «другой» стороне «root» ». Это доступно из источника t
как выражение с псевдонимом как dnode
.
В противном случае мы рассмотрим строки для «второго» уровня, i = 2
. (В данном конкретном случае тест на i = 2
можно опустить, но он включен в систему для полноты, и на всякий случай мы собираемся расширить этот подход, чтобы получить три уровня (вздох) или больше (о мой!).
Здесь мы должны знать, какую сторону (от или до) соответствует первому уровню, и мы просто тянуть другую сторону. Если t.dnode
матчи на стороне, мы тянем другую сторону.
Наконец, мы используем GROUP BY, чтобы свернуть дубликаты.
Поскольку нам все равно, на каком уровне они были, опускаем возвращаемый t.i
, что даст нам уровень.
РЕЗЮМЕ
Я не думаю, что это больше, чем просто ваш запрос. И я понятия не имею, как производительность будет сравнивать. Но приятно иметь другие утверждения для сравнения производительности.
Является ли ваше намерение идти только на два уровня в глубину? Поэтому, если node1 => node2 => node3 => node4. Для node1 вам нужны только node2 и node3, но не node4? – bobwienholt
Да, я намерен идти ровно на 2 уровня глубиной – PainFly
Являются ли эти соединения однонаправленными или двусторонними? –