繁体   English   中英

消息传递应用程序的复杂SQL查询

Complex SQL query for messaging app

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我正在使用PostgreSQL 9.3.4在Django 1.6.2应用程序中构建消息传递功能。 在用户的“消息”主页上,我将显示一个用户与其他用户的对话列表。 每个对话“平铺”或块将显示该对话中另一个用户的图片和名称,该对话中最后一条消息的发送日期以及该最后一条消息中的前25个字符。 如果最后一条消息是由正在查看这些对话的用户发送的,我还将显示一个小的“答复”图标。 我已经查询到可以识别查看器与所有其他用户之间的所有对话的地步,但是我在从“用户”和“消息”表中提取所需字段时遇到了麻烦。

我的表格(显示在底部)是用户,消息和对话。 尽管我已经实现了表模式,以便用户和会话之间存在多对多关系,但一开始我将创建我的界面,以便用户只能向其他用户发送消息,而不能多个用户。

当我对下面显示的数据运行查询时,我要获取的是用户3、4、5的对话和用户ID以及相关的用户名,对话中的最后一条消息,发送者以及发送日期。 相反,我得到了错误:

 ERROR: syntax error at or near "WHERE" 

谁能帮我解决这个问题? 我对速度比对优雅更感兴趣。

测试用例

对话用户链接表中的数据:

 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
1 个回复

修正语法

基本上,您只需要将WHERE条件移动到适当的位置,如@Lamak注释

SELECT  ...
FROM conversation_user cu
INNER JOIN ...
WHERE conversation_id IN (SELECT conversation_id FROM conversation_user WHERE user_id = 32) AND user_id != 32
ORDER BY m.send_date DESC
LIMIT 1;

快一点

根据评论:

我正在尝试选择用户32进行的每个对话中的最后一条消息。

SELECT cu.conversation_id
     , ufrom.username AS from_user
     , uto.username   AS to_user
     , m.message
     , m.send_date
FROM   conversation_user cu
LEFT   JOIN LATERAL (
   SELECT from_user_id, to_user_id, message, send_date
   FROM   message   m
   WHERE  m.conversation_id = cu.conversation_id
   ORDER  BY send_date DESC
   LIMIT  1
   ) m ON TRUE
LEFT   JOIN auth_user ufrom ON ufrom.id = m.from_user_id
LEFT   JOIN auth_user uto   ON uto.id = m.to_user_id
WHERE  cu.user_id = 32;

笔记

数据库设计

  • 该查询假定(user_id, conversation_id)UNIQUE已在注释中确认了这一点 确保添加实际的UNIQUE约束,该约束会自动提供急需的索引。

  • message上的索引(conversation_id, send_date DESC)也将有所帮助。 细节:

  • 假设auth_user.id是PK,那么它将被索引。

  • message.to_user_uid可能应该是to_user_id ,例如from_user_id

  • 您可能想要添加另一个FK来保持一致:

     "message_to_user_id_fkey" FOREIGN KEY (to_user_id) REFERENCES auth_user(id) 

    不知道为什么您认为自己需要DEFERRABLE INITIALLY DEFERRED 如果您不知道需要此功能,请将其删除。 这是出于特殊目的,使常规操作的成本更高。

  • 如果只有两个用户可以参加同一对话 ,则完全删除 conversation_user user1并添加user1user2或类似于conversation将更为有效-除非用户/对话的每种组合都有更多的属性。 也可能简化message 您只需要布尔信息,而不是from_userto_user
    根据关系理论, conversation可以看作是表auth_user与自身之间多对多关系的一种实现。

1 库存应用程序的复杂SQL查询

给定以下2个表,我需要找到具有正确数量的所有零件的仓库,以制造特定的工具包,或更合适的是,每个仓库可以构建多少个工具包。 库存表:仓库,零件和现有数量 套件表:套件,零件,QuantityForKit 例如:Kit1需要Part1的一部分,Part2的2和Part3的1。 仓库 ...

2 邮件系统的收件箱SQL查询

我正在使用php和mysql构建消息系统,并使用本教程作为我的指南http://aaronsaray.com/blog/2010/07/27/facebook-message-system-in-php 我正在收件箱页面上工作,并且收件箱有问题,因为它不会选择已阅读的邮件,因此当用户打开其 ...

2012-01-17 20:54:47 1 919   php/ mysql
3 消息应用程序的 MongoDB 聚合查询

我正在开发一个具有消息功能(聊天)的应用程序,我想获取我拥有或向我发送消息的所有用户,并按照最近通信的联系人到达的顺序对所有这些用户进行分组最佳。 并计算我从其他用户那里收到但我尚未阅读的所有消息。 Mongo 消息模型 我的 MongoDB 聚合 我想获取的数据示例 比如说我们有两个用 ...

4 复杂的嵌套 SQL 查询

更新我将调试我的问题并重新发布更多详细信息! 对于造成的混乱,我深表歉意! 更新所有评论或发布答案的人,我会将您链接到我的重新发布,感谢您花时间检查我的问题和评论/答案! 我会让我的问题简单明了; 当我包含前三个子查询时,下面的代码块会生成语法错误。 我究竟做错了什么? 提前谢谢了。 ...

2018-02-18 21:07:42 1 56   sql
5 SQL查询复杂的ID

我有一个要通过ID缩写的表。我使用的ID有点复杂。 ID的形式为 EM_ {AZ} {} INT 每个Id以EM_开头,后跟一个字符形式AZ和每个字母一个递增的INT。 我想通过ID来缩短表格。当我这样做时,我得到以下结果。 作为示例,该表的假想快照形式为 我想 ...

6 需要复杂的SQL查询

我有一个表people有(其中包括)字段givenName和gender 。 我想根据其他行的最佳猜测来更新所有那些gender=NULL行。 也就是说,如果以下各行 我要进行以下更改: 因此,正确地确定了约翰是男性,简是女性,而尚不清楚山姆是萨曼莎还是塞缪尔。 我知道我的 ...

2017-02-11 11:43:18 2 48   mysql
7 优化复杂的SQL查询

我正在使用Azure SQL Server数据库。 我已经编写了一个sql查询来生成reprot。 这里是: 有什么方法可以优化此查询。 超时问题来了。 我已经在存储过程中编写了此查询,并使用linq实体框架调用了该存储过程。 之前我曾使用过join,但它的速度较慢,因此尝 ...

8 SQL复杂SELECT查询

问题是:我有两个表TableA和TableB ,如下所示: TableA的列: TableB的列: 其他信息: TableA.ID2在TableB.ID上联接 在TableA中,可以有几行具有相同的ID,但具有不同的ID2和Flag1值。 像这样 : ...

9 SQL筛选复杂查询

我有三个表: 产品 PRODUCT_ATTRIBUTE 属性 所有属性都在ATTRIBUTE表中。 产品和属性之间的链接位于PRODUCT_ATTRIBUTE中。 现在,我需要根据属性过滤产品: 例如:我需要模式为“固态”且场合为“休闲”的产品: 结 ...

2015-11-29 07:36:28 3 65   mysql/ sql
10 SQL查询复杂联接

我有几个表,我想输出 MAHASISWA上的NAMA,而MAHASISWA上的NIM = MHS_MAKUL上的NIM_MHS,其中(N_TUGAS ='C'和N_MID ='B')和ID_MHS_MAKUL上NILAI_MAKUL = ID上MHS_MAKUL 这里的表和列的列表 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM