2014-01-24 81 views
2

我有一张表,用于保存有关用户之间发送的消息的信息。它看起来是这样的:查询查询或分组循环

MessageID | MessageIDReference | MessageSubject | Body  | Date 
1   NULL     Test    Hello  10/01/2014 
2   1     RE: Test   Goodbye 11/01/2014 
3   1     RE: Test   Hello  11/01/2014 
....... 
50   45     RE: Subject  Blah  12/12/2014 

所以创建将在MessageIDReferenceNULL值(因为它是一个新的消息不是回复)的第一条消息。当用户回复邮件时,它会将原始邮件的MessageID插入到MessageIDReference列中,以便我们知道它回复了哪个邮件。好而简单!

在我的网页我想在一个区域内显示该对话中的第一条消息,然后任何后续答复该消息所以它很容易看到谈话的流动,像这样的:

<ol> 
<cfloop query="messages"> 
<li> 
    #MessageSubject# #Body# 
     <ol> 
     <!--- I want replies to this message here somehow ---> 
     <li>1st reply</li> 
     <li>2nd reply</li> 
     etc etc 
     </ol> 
</li> 
    </cfloop> 
<ol> 

我认为它可以通过在每个<cfloop>标签内的某种组来完成,但我不知道如何。我现在认为它必须在内部循环中使用查询查询来完成,以便它返回每个MessageID的所有答复并输出这些答案。

查询的查询工作,当我做这样的事情:

<cfquery name="Messages"> 
    SELECT * FROM Messages 
    </cfquery> 

<ol> 
    <cfquery type="query" name="MessagesNew"> 
    SELECT * 
    FROM Messages 
    WHERE MessageIDReference IS NULL 
    </cfquery> 
    <cfloop query="MessagesNew"> 
    <li> #MessagesNew.MessageSubject# #MessagesNew.Body# 
    <cfquery type="query" name="MessagesReplies"> 
    SELECT * 
    FROM Messages 
    WHERE MessageIDReference = #MessagesNew.MessageID# 
    </cfquery> 
    <ol> 
     <cfloop query="MessagesReplies"> 
     <li>#MessagesReplies.MessageSubject# #MessagesReplies.Body#</li> 
     </cfloop> 
    </ol> 
    </li> 
    </cfloop> 
</ol> 
+0

您最好不要使新消息的MessageIDReference无效。相反,使其与MessageID相同。这当然会使这个任务更容易。顺便说一下,只有只有一条消息没有引用时,您的查询样本查询才会有效。 –

+0

@DanBracuk我编辑了我的文章,所以它更清晰一点。我之前在冲,并没有完成我的例子 –

+0

为什么你会急于提问? –

回答

4

丹做一个伟大的建议,但这里是一个查询,将工作,以获得原始消息以及任何答复 - 分页,使第一行是原始消息,其余的都是按时间顺序的回复。

<cfquery type="query" name="MessagesReplies"> 
    SELECT * 
    FROM Messages 
    WHERE MessageIDReference = <cfqueryparam cf_sql_type="cf_sql_integer" value="#MessagesNew.MessageID#" /> 
    OR MessageID = <cfqueryparam cf_sql_type="cf_sql_integer" value="#MessagesNew.MessageID#" /> 
    ORDER BY MessageId, date 
</cfquery> 

你在何处运行MessageIDReference为NULL将在每一个线程返回的第一个消息,所以你需要选择一个基于ID查询。

注意使用cfqueryparam,你应该总是参数化你的查询。总是。

+0

如果messageid字段是自动增量,则可能不需要按日期排序部分。 –

+2

我更喜欢在警告方面出错:D –

1

这种方式可能更容易。

<cfquery name = "GetMessages" datasource="something"> 
select MessageId, ifnull(MessageIDReference, MessageId) Message 
, other fields 
from your message table 
where whatever 
order by Message, MessageId 

<cfoutput query="GetMessages" group = "message"> 
#grouped data# 
<cfoutput> 
#ungrouped data# 
</cfoutput> 
</cfoutput> 

注意,IFNULL函数是特定的数据库。你没有指定你的数据库引擎。如果你正在使用的东西没有相同的功能,你可以使用这个

case when MessageIDReference is not null MessageIDReference 
else MessageId end Message 

另外请注意,你的问题比你想象的更复杂。假设你只想要某个日期范围的数据。如果是这样,您将需要进一步过滤,以仅包含那些在该日期范围内启动的线程。一个子查询可能会起作用,但我会给你一个自己解决的机会。

+1

FWIW,尝试['coalesce'](http://en.wikipedia.org/wiki/Null_%28SQL%29#COALESCE)以获得更多的数据库中立选择。它不是一个确切的等价物,但是比像'ifnull','isnull'之类的供应商特定功能往往具有更广泛的支持。 – Leigh