1

前幾天我問了一個關於1,2和3度連接的問題。 Question Link和@Snoopy給了一篇文章鏈接,可以解決我所有的問題。 Article Link如何在SQL Server中重寫此查詢(PostgreSQL)?

我仔細檢查了這篇文章,但我無法使用帶有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; 

正如我所說的,我不知道該怎麼寫與使用CTE SQL Server中的遞歸查詢。搜索並檢查了this page,但仍然沒有運氣。我無法運行查詢。

回答

4

更換||級聯如果有人有興趣,這裏就是答案;

我設法將有問題的查詢轉換爲SQL;

  1. 將整數值轉換爲varchar(MAX)。如果你沒有指定varchar的長度爲MAX,你會得到「類型不匹配錨點和列中的遞歸部分...」

  2. I replaced ||到+

  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

SQL Server上的遞歸CTE應該是相同的(至少在最近的版本中,如果我沒有弄錯,這是在SQL Server 2005中引入的),只是忽略了recursive關鍵字。

注意SQL Server不符合SQL標準,爲此你需要+

+0

我刪除了遞歸,它的工作原理,但我無法運行此查詢。 'SELECT edges.a as a, edges.b as b, 1 AS距離, a +'。' + b +'。' as path FROM edges' 錯誤:轉換varchar值'。'時轉換失敗。到數據類型int 我試圖使用CAST但沒有成功。 – 2011-05-01 11:48:08

+0

@Burak:顯然'a'和'b'不是varchar列。您需要投射它們才能連接它們。嘗試'cast(edges.a as varchar)+'。' + cast(edges.b as varchar)' – 2011-05-01 11:55:22

+0

我設法運行此查詢:'SELECT edges.a as a, edges.b as b, 1 AS距離, CAST(a AS VARCHAR(10))+ '' + CAST(b AS VARCHAR(10))+'。'as path FROM edges' – 2011-05-01 11:56:11