2013-07-31 105 views
0

我被困在這個邏輯問題中,我不知道如何繼續。訂購SELECT - 邏輯問題(SQL)

我有兩列:ID和FOLDERID。由於文件夾也可以是子文件夾,因此我希望通過先選擇沒有folderid(根文件夾)的文件夾,然後選擇其子文件夾,然後再訂購我的結果。所以這種方式我不會有任何問題,如「文件夾X不存在」。

在這個例子中,我不能通過FOLDERID ASC和/或ID ASC的簡單排序來得到我所需要的。

正確的結果是3之一:

  1. 首先,我得到的ID 2 「泰斯特」 文件夾中,因爲它已經folderid 0 =根之一。
  2. 現在我想 「Controladoria」 文件夾,因爲folderid是2,所以它需要的文件夾ID 2被首先創建(泰斯特)
  3. 「PCP」 的文件夾,即需要與ID 1(Controladoria)夾
  4. 「Pasta1」文件夾中,需要與ID 3(PCP)
  5. 上和文件夾...

我已經試過多個訂單通過多種方式和加入/留在同一個表中加入,但無法弄清楚我該如何做到這一點。

任何想法?

+0

如果你沒有明確指定'ORDER BY',那麼排序是***未定義*** - 那裏***沒有隱式***排序(例如通過創建日期或類似的東西)一個SQL表 –

+1

你使用了什麼數據庫? –

+2

如果我正確理解你,你想要像樹中一樣排序文件夾(深度優先搜索)?如果是這樣,這涉及到遞歸,這沒有什麼SQL是很好的。 – contradictioned

回答

1

使用簡單的遞歸查詢可以得到這些結果。

;WITH CTE 
    AS (SELECT *, 
       1 RN 
     FROM TABLE1 
     WHERE FOLDERID = 0 
     UNION ALL 
     SELECT T1.*, 
       T2.RN + 1 
     FROM TABLE1 T1 
       INNER JOIN CTE T2 
         ON T1.FOLDERID = T2.ID) 
SELECT [ID], 
     [NAME], 
     [FOLDERID] 
FROM CTE 
ORDER BY RN 

使用此查詢您還可以處理多個子文件夾。

看看SQL Fiddle上的工作示例。
如果你想要遞歸查詢的好消息,請看this blog

2

您可以使用CASE語句ORDER,爲您的例子,這會工作,但它聽起來就像你可能是一個遞歸的層次結構,對於這句法將RDBMS變化後:

ORDER BY CASE WHEN FolderID = 0 THEN 0 ELSE 1 END, ID 
+0

不知道我們可以在ORDER BY中使用CASE。我正在使用一個緊湊版本的SQL SERVER,我認爲它工作。謝謝! 但是我需要問一下,如果你能解釋我在這段代碼中做了什麼命令。當我們使用ORDER BY 0,ORDER BY 1時,是不是按列索引命令?或者案例陳述的結果正在處理另一種我不知道的方法? – Sawd

+1

上面的case語句的輸出是每行的數值0和1,如果你說'ORDER BY 1'你會使用列索引。可以這樣想,如果你把'CASE'語句放在你的'SELECT'中,你會得到每一行的值,那麼你可以用這個值來命令。只需將它放在'ORDER'中即可避免返回輸出。 –

+0

當子文件夾ID大於其父ID時,這將無法正常工作。 – Sawd

2

你可以選擇對於分層查詢,如果你的dbms支持這個。在Oracle語法:

select id 
     , name 
     , folderid 
     , sys_connect_by_path (name, '/') path 
     from table t 
connect by prior id = folderid 
start with folderid = 0 
    order by path 
     ; 
+0

這幫了我很多。我正在使用SQL SERVER,並發現與Oracle的CONNECT BY等價的東西。這符合我所需要的:-) – Sawd

1

基於黑洞響應,我發現了一個Oracle的CONNECT BY相當於上解決了我的問題。

WITH n([ID], [NAME], [OWNER], [FOLDERID]) AS 
    (SELECT [ID], [NAME], [OWNER], [FOLDERID] 
    FROM [RM_REPORTS_FOLDERS] 
    WHERE [FOLDERID] = 0 
     UNION ALL 
    SELECT nplus1.[ID], nplus1.[NAME], nplus1.[OWNER], nplus1.[FOLDERID] 
    FROM [RM_REPORTS_FOLDERS] as nplus1, n 
    WHERE n.[ID] = nplus1.[FOLDERID]) 
SELECT [ID], [NAME], [OWNER], [FOLDERID] FROM n 
+0

不保證該查詢的順序。什麼在測試中起作用可能不適用於生產。 – Anon

+0

向cte添加深度增量器並將其用於訂購 – Anon

+0

您的意思是像Gidil的響應?我會嘗試。 – Sawd