【发布时间】:2015-03-13 03:59:55
【问题描述】:
我正在使用 PostgreSQL 9.3.4 在 Django 1.6.2 应用程序中构建消息传递功能。在用户的“消息”主页上,我将显示用户与其他用户的对话列表。每个对话“图块”或块将显示该对话中其他用户的图片和姓名、该对话中最后一条消息的发送日期以及该最后一条消息中的前 25 个字符。如果最后一条消息是由正在查看这些对话的用户发送的,我还会显示一个小的“回复”图标。我的查询已经到了可以识别查看者和所有其他用户之间的所有对话的地步,但是我无法从用户和消息表中提取我需要的字段。
我的表格(显示在底部)是用户、消息和对话。虽然我已经实现了我的表模式,以便在用户和对话之间存在多对多的关系,但一开始我将创建我的界面,以便用户只能向另一个用户发送消息,而不是多个用户。
当我对下面显示的数据运行查询时,我试图返回的是用户 3、4、5 的对话和用户 ID 以及他们关联的用户名,该对话中的最后一条消息,谁发送了它,以及它的发送日期。相反,我收到了错误:
ERROR: syntax error at or near "WHERE"
谁能帮我解决这个问题?我对速度比对优雅更感兴趣。
测试用例
conversation_user 链接表中的数据:
id | conversation_id | user_id
----+-----------------+---------
1 | 1 | 32
2 | 1 | 3 <- want this
3 | 2 | 32
4 | 2 | 4 <- want this
6 | 3 | 3
7 | 3 | 1
8 | 4 | 32
9 | 4 | 5 <- want this
10 | 5 | 7
11 | 5 | 9
我想返回的行。每条消息都是该对话中的最后一条消息。
conversation_id | user_id | username | from_user | message | send_date
----------------+---------+-----------+-----------+---------+----------
1 | 3 | user3 | u3 or u32 | <msg3> | <date>
2 | 4 | user4 | u4 or u32 | <msg4> | <date>
4 | 5 | user5 | u5 or u32 | <msg5> | <date>
不工作的查询:
SELECT cu.conversation_id,
cu.user_id,
au.username,
m.from_user,
m.message,
m.send_date
FROM conversation_user cu
INNER JOIN auth_user au ON cu.user_id = au.id
INNER JOIN message m ON cu.conversation_id = m.conversation_id
ORDER BY m.send_date DESC LIMIT 1
WHERE conversation_id IN
(SELECT conversation_id
FROM conversation_user
WHERE user_id = 32)
AND user_id != 32;
表定义
# auth_user
--------------+--------------------------+------------------------------
id | integer | not null default nextval(...
username | character varying(30) | not null
Referenced by:
TABLE "conversation_user" CONSTRAINT "conversation_user_user_id_fkey" FOREIGN KEY (user_id) REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED
TABLE "message" CONSTRAINT "message_from_user_id_fkey" FOREIGN KEY (from_user_id) REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED
# conversation
------------+--------------------------+--------------------------------
id | integer | not null default nextval(...
start_date | timestamp with time zone | not null
Referenced by:
TABLE "conversation_user" CONSTRAINT "conversation_id_refs_id_4344ca71" FOREIGN KEY (conversation_id) REFERENCES conversation(id) DEFERRABLE INITIALLY DEFERRED
TABLE "message" CONSTRAINT "message_conversation_id_fkey" FOREIGN KEY (conversation_id) REFERENCES conversation(id) DEFERRABLE INITIALLY DEFERRED
# conversation_user
-----------------+---------+--------------------------------------------
id | integer | not null default nextval(...
conversation_id | integer | not null
user_id | integer | not null
Foreign-key constraints:
"conversation_id_refs_id_4344ca71" FOREIGN KEY (conversation_id) REFERENCES conversation(id) DEFERRABLE INITIALLY DEFERRED
"conversation_user_user_id_fkey" FOREIGN KEY (user_id) REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED
# message
Column | Type |
-----------------+--------------------------+---------------------------
id | integer | not null default nextval(...
conversation_id | integer | not null
from_user_id | integer | not null
to_user_uid | integer | not null
message | text | not null
send_date | timestamp with time zone | not null
Foreign-key constraints:
"message_conversation_id_fkey" FOREIGN KEY (conversation_id) REFERENCES conversation(id) DEFERRABLE INITIALLY DEFERRED
"message_from_user_id_fkey" FOREIGN KEY (from_user_id) REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED
【问题讨论】:
-
将
ORDER BY移动到WHERE条件之后:WHERE conversation_id..... ORDER BY m.send_date DESC LIMIT 1 -
为什么要编写原始 SQL 而不是使用 Django 模型层?
-
@DanielRoseman,我使用的是原始 SQL,因为虽然我不是 SQL 专家,但我更喜欢编写 SQL,而不是使用 Django 的 ORM 命令。另外,我想消除由于 Django 必须将 ORM 命令转换为 SQL 而导致的任何可能的性能开销。
-
@DanielRoseman:使用 Django 模型层有什么好处?
-
@Lamak,感谢您的意见,但我必须感谢 Erwin,因为他为我提供了大量帮助。
标签: sql django postgresql database-design greatest-n-per-group