2010-01-15 49 views
0

我有以下的方法,我需要ORDER BY的结果:如何订购通过递归SQL查询

def has_attachments? 
    attachments.size > 0 || (!parent.nil? && parent.has_attachments?) 
end 

我有这个迄今为止得到:

ORDER BY 
CASE WHEN attachments.size > 0 THEN 1 ELSE 
    (CASE WHEN parent_id IS NULL THEN 0 ELSE 
     (CASE message.parent ...what goes here) 
       END 
    END 
END 

我可能会寻找在这个错误,因为我没有递归SQL的经验。基本上,我想通过消息或其父母是否有附件来进行排序。如果附件大小大于0,我可以停止并返回1.如果邮件的附件大小为0,我现在检查它是否有父项。如果它没有父节点,那么就没有附件,但是如果它有父节点,那么我基本上必须为父节点执行相同的查询情况逻辑。

UPDATE 表看起来像这样

+---------------------+--------------+------+-----+---------+----------------+ 
| Field    | Type   | Null | Key | Default | Extra   | 
+---------------------+--------------+------+-----+---------+----------------+ 
| id     | int(11)  | NO | PRI | NULL | auto_increment | 
| message_type_id  | int(11)  | NO | MUL |   |    | 
| message_priority_id | int(11)  | NO | MUL |   |    | 
| message_status_id | int(11)  | NO | MUL |   |    | 
| message_subject_id | int(11)  | NO | MUL |   |    | 
| from_user_id  | int(11)  | YES | MUL | NULL |    | 
| parent_id   | int(11)  | YES | MUL | NULL |    | 
| expires_at   | datetime  | YES | MUL | NULL |    | 
| subject_other  | varchar(255) | YES |  | NULL |    | 
| body    | text   | YES |  | NULL |    | 
| created_at   | datetime  | NO | MUL |   |    | 
| updated_at   | datetime  | NO |  |   |    | 
| lock_version  | int(11)  | NO |  | 0  |    | 
+---------------------+--------------+------+-----+---------+----------------+ 

凡PARENT_ID指父的消息,如果它存在。 谢谢!

+0

如果您发布了您正在使用的表格的说明,它将更容易帮助您。 – 2010-01-15 12:23:27

+0

我添加了上面的表格说明 – Tony 2010-01-15 19:31:59

回答

0

我假定每个附件都存储在带有message_id字段的附件表中。

WITH RECURSIVE msgs(id, parent_id, has_attachments, current_ancestor_id) AS 
(
    SELECT DISTINCT 
    m.id, 
    m.parent_id, 
    CASE WHEN a.message_id IS NULL THEN 0 ELSE 1 END AS has_attachments, 
    -- If the message has attachments, there is no point in going to any ancestors 
    CASE WHEN has_attachments = 0 THEN m.parent_id ELSE NULL END AS current_ancestor_id 
    FROM messages m 
    LEFT JOIN attachments a 
     ON m.id = a.message_id 

    UNION ALL 

    SELECT 
    m2.id, 
    m2.parent_id, 
    CASE WHEN (CASE WHEN a.message_id IS NULL THEN 0 ELSE 1 END) > m2.has_attachments THEN (CASE WHEN a.message_id IS NULL THEN 0 ELSE 1 END) ELSE m2.has_attachments END, 
    CASE WHEN has_attachments = 0 THEN m1.parent_id ELSE NULL END AS current_ancestor_id 
    FROM messages m1 
    LEFT JOIN attachments a 
     ON m1.id = a.message_id 
    INNER JOIN msgs m2 
     ON m1.id = m2.current_ancestor_id 
) 
SELECT 
    id, 
    parent_id, 
    has_attachments 
FROM msgs 
WHERE current_ancestor_id IS NULL 
ORDER BY 
    has_attachments DESC;