Как переписать этот запрос (PostgreSQL) в SQL Server? - PullRequest
1 голос
/ 29 апреля 2011

Несколько дней назад я задал вопрос о связях 1,2 и 3. степени. Ссылка на вопрос и @Snoopy дали ссылку на статью, которая может решить все мои проблемы. Ссылка на статью

Я внимательно изучил эту статью, но мне не удалось использовать рекурсивный запрос с SQL Server.

Запрос PostgreSQL:

SELECT a AS you,
   b AS mightknow,
   shared_connection,
   CASE
     WHEN (n1.feat1 = n2.feat1 AND n1.feat1 = n3.feat1) THEN 'feat1 in common'
     WHEN (n1.feat2 = n2.feat2 AND n1.feat2 = n3.feat2) THEN 'feat2 in common'
     ELSE 'nothing in common'
   END AS reason
 FROM (
 WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS
 ( SELECT a, b, 1 AS distance,
     a || '.' || b || '.' AS path_string,
     b AS direct_connection
FROM edges2
 WHERE a = 1 -- set the starting node

 UNION ALL

 SELECT tc.a, e.b, tc.distance + 1,
     tc.path_string || e.b || '.' AS path_string,
     tc.direct_connection
FROM edges2 AS e
JOIN transitive_closure AS tc ON e.a = tc.b
 WHERE tc.path_string NOT LIKE '%' || e.b || '.%'
 AND tc.distance < 2
 )
 SELECT a,
   b,
   direct_connection AS shared_connection
 FROM transitive_closure
 WHERE distance = 2
 ) AS youmightknow
 LEFT JOIN nodes AS n1 ON youmightknow.a = n1.id
 LEFT JOIN nodes AS n2 ON youmightknow.b = n2.id
 LEFT JOIN nodes AS n3 ON youmightknow.shared_connection = n3.id
 WHERE (n1.feat1 = n2.feat1 AND n1.feat1 = n3.feat1)
 OR (n1.feat2 = n2.feat2 AND n1.feat2 = n3.feat2);

или просто

WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS
( SELECT a, b, 1 AS distance,
     a || '.' || b || '.' AS path_string
FROM edges
WHERE a = 1 -- source

UNION ALL

SELECT tc.a, e.b, tc.distance + 1,
     tc.path_string || e.b || '.' AS path_string
FROM edges AS e
JOIN transitive_closure AS tc ON e.a = tc.b
WHERE tc.path_string NOT LIKE '%' || e.b || '.%'
)
SELECT * FROM transitive_closure
WHERE b=6 -- destination
ORDER BY a, b, distance;

Как я уже сказал, я не знаю, как написать рекурсивный запрос для SQL Server с использованием CTE. Сделал поиск и осмотрел эту страницу но все равно не повезло. Я не смог выполнить запрос.

Ответы [ 2 ]

4 голосов
/ 01 мая 2011

Если кому-то интересно, вот ответ;

Мне удалось преобразовать рассматриваемый запрос в SQL путем:

  1. преобразования целочисленных значений в varchar (MAX),Если вы не укажете длину varchar как MAX, вы получите «Типы не совпадают между якорем и рекурсивной частью в столбце ...»

  2. Я заменил||к +

  3. я добавил;к началу запроса

  4. Наконец, как предложило @a_horse_with_no_name, я удалил RECURSIVE из запроса.

Результат;

;WITH transitive_closure(a, b, distance, path_string) AS
( SELECT a, b, 1 AS distance,
 CAST(a as varchar(MAX)) + '.' + CAST(b as varchar(MAX)) + '.' AS path_string
FROM edges
WHERE a = 1 -- source

UNION ALL

SELECT tc.a, e.b, tc.distance + 1, 
CAST(tc.path_string as varchar(MAX)) + CAST(e.b as varchar(MAX)) + '.' AS path_string
FROM edges AS e
JOIN transitive_closure AS tc ON e.a = tc.b
WHERE tc.path_string NOT LIKE '%' + CAST(e.b as varchar(MAX)) + '.%'
)
SELECT * FROM transitive_closure
WHERE b=6 -- destination
ORDER BY a, b, distance;
2 голосов
/ 29 апреля 2011

Рекурсивный CTE должен быть таким же на SQL Server (по крайней мере в последней версии, он был введен в SQL Server 2005, если я не ошибаюсь), просто пропустите ключевое слово recursive.

Обратите внимание, что SQL Server не соответствует стандарту SQL, и поэтому вам необходимо заменить конкатенацию || на +

...