从 SQLite 数据库中获取带有最后一条消息的联系人
Fetch contacts with last message from SQLite database
我已经有一段时间没有使用 SQL 查询了。今天我遇到了从 table 中获取数据并从另一个 table 中引用记录的问题。我需要支持构建一个有效的 SQL 查询,它将与 SQLite 数据库一起使用。
问题
给定 SQLite 数据库中的以下 tables:
CREATE TABLE IF NOT EXISTS "contacts" (
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
"name" text NOT NULL
);
CREATE TABLE IF NOT EXISTS "messages" (
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
"date" integer NOT NULL,
"senderId" integer NOT NULL,
"recipientId" integer NOT NULL,
"text" text NOT NULL
);
其中:
messages.senderId
引用 contacts.id
messages.recipientId
引用 contacts.id
对于具有提供的 ID 的联系人,我想获取所有其他联系人以及发送给该联系人或从该联系人接收的最新消息。结果应按消息日期降序排列。
一个例子
例如,如果我们有以下联系人:
+----+------+
| id | name |
+----+------+
| 1 | A |
+----+------+
| 2 | B |
+----+------+
| 3 | C |
+----+------+
以及以下消息:
+----+------+----------+-------------+----------+
| id | date | senderId | recipientId | text |
+----+------+----------+-------------+----------+
| 1 | 10 | 1 | 2 | A→B @ 10 |
+----+------+----------+-------------+----------+
| 2 | 20 | 2 | 1 | B→A @ 20 |
+----+------+----------+-------------+----------+
| 3 | 30 | 1 | 2 | A→B @ 30 |
+----+------+----------+-------------+----------+
| 4 | 40 | 1 | 3 | A→C @ 40 |
+----+------+----------+-------------+----------+
| 5 | 50 | 3 | 1 | C→A @ 50 |
+----+------+----------+-------------+----------+
| 6 | 60 | 2 | 3 | B→C @ 60 |
+----+------+----------+-------------+----------+
| 7 | 70 | 3 | 2 | C→B @ 70 |
+----+------+----------+-------------+----------+
联系人“A”的提取结果应如下所示:
+---------------+---------------+---------------+
| contacts.name | messages.date | messages.text |
+---------------+---------------+---------------+
| C | 50 | C→A @ 50 |
+---------------+---------------+---------------+
| B | 30 | A→B @ 30 |
+---------------+---------------+---------------+
相同的获取,但对于联系人“B”,应产生以下输出:
+---------------+---------------+---------------+
| contacts.name | messages.date | messages.text |
+---------------+---------------+---------------+
| C | 70 | C→B @ 70 |
+---------------+---------------+---------------+
| A | 30 | A→B @ 30 |
+---------------+---------------+---------------+
对于联系人“C”,我们应该得到:
+---------------+---------------+---------------+
| contacts.name | messages.date | messages.text |
+---------------+---------------+---------------+
| B | 70 | C→B @ 70 |
+---------------+---------------+---------------+
| A | 50 | C→A @ 50 |
+---------------+---------------+---------------+
我失败的尝试
老实说,我感到迷茫,我不确定我正在做的事情是否接近正确的解决方案,但这是我尝试使用的 SQL 查询:
WITH "lastMessage" AS (
SELECT *, MAX("date")
FROM "messages"
GROUP BY "senderId" OR "recipientId"
)
SELECT "contacts"."name", "lastMessage"."date", "lastMessage"."text"
FROM "contacts"
JOIN "lastMessage"
ON ("lastMessage"."senderId" = "contacts"."id")
OR ("lastMessage"."recipientId" = "contacts"."id")
WHERE "contacts"."id" != 1
ORDER BY "lastMessage"."date" DESC
很遗憾,它不起作用。
任何反馈将不胜感激!
加入 messages
到 contacts
的 2 个副本并聚合:
SELECT c2.name, MAX(m.date) last_date, m.text
FROM messages m
INNER JOIN contacts c1 ON c1.id IN (m.senderId, m.recipientId)
INNER JOIN contacts c2 ON c2.id IN (m.senderId, m.recipientId) AND c1.id <> c2.id
WHERE c1.name = ?
GROUP BY c2.id
ORDER BY last_date DESC;
将 ?
更改为您想要的联系人姓名。
参见demo。
我已经有一段时间没有使用 SQL 查询了。今天我遇到了从 table 中获取数据并从另一个 table 中引用记录的问题。我需要支持构建一个有效的 SQL 查询,它将与 SQLite 数据库一起使用。
问题
给定 SQLite 数据库中的以下 tables:
CREATE TABLE IF NOT EXISTS "contacts" (
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
"name" text NOT NULL
);
CREATE TABLE IF NOT EXISTS "messages" (
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
"date" integer NOT NULL,
"senderId" integer NOT NULL,
"recipientId" integer NOT NULL,
"text" text NOT NULL
);
其中:
messages.senderId
引用contacts.id
messages.recipientId
引用contacts.id
对于具有提供的 ID 的联系人,我想获取所有其他联系人以及发送给该联系人或从该联系人接收的最新消息。结果应按消息日期降序排列。
一个例子
例如,如果我们有以下联系人:
+----+------+
| id | name |
+----+------+
| 1 | A |
+----+------+
| 2 | B |
+----+------+
| 3 | C |
+----+------+
以及以下消息:
+----+------+----------+-------------+----------+
| id | date | senderId | recipientId | text |
+----+------+----------+-------------+----------+
| 1 | 10 | 1 | 2 | A→B @ 10 |
+----+------+----------+-------------+----------+
| 2 | 20 | 2 | 1 | B→A @ 20 |
+----+------+----------+-------------+----------+
| 3 | 30 | 1 | 2 | A→B @ 30 |
+----+------+----------+-------------+----------+
| 4 | 40 | 1 | 3 | A→C @ 40 |
+----+------+----------+-------------+----------+
| 5 | 50 | 3 | 1 | C→A @ 50 |
+----+------+----------+-------------+----------+
| 6 | 60 | 2 | 3 | B→C @ 60 |
+----+------+----------+-------------+----------+
| 7 | 70 | 3 | 2 | C→B @ 70 |
+----+------+----------+-------------+----------+
联系人“A”的提取结果应如下所示:
+---------------+---------------+---------------+
| contacts.name | messages.date | messages.text |
+---------------+---------------+---------------+
| C | 50 | C→A @ 50 |
+---------------+---------------+---------------+
| B | 30 | A→B @ 30 |
+---------------+---------------+---------------+
相同的获取,但对于联系人“B”,应产生以下输出:
+---------------+---------------+---------------+
| contacts.name | messages.date | messages.text |
+---------------+---------------+---------------+
| C | 70 | C→B @ 70 |
+---------------+---------------+---------------+
| A | 30 | A→B @ 30 |
+---------------+---------------+---------------+
对于联系人“C”,我们应该得到:
+---------------+---------------+---------------+
| contacts.name | messages.date | messages.text |
+---------------+---------------+---------------+
| B | 70 | C→B @ 70 |
+---------------+---------------+---------------+
| A | 50 | C→A @ 50 |
+---------------+---------------+---------------+
我失败的尝试
老实说,我感到迷茫,我不确定我正在做的事情是否接近正确的解决方案,但这是我尝试使用的 SQL 查询:
WITH "lastMessage" AS (
SELECT *, MAX("date")
FROM "messages"
GROUP BY "senderId" OR "recipientId"
)
SELECT "contacts"."name", "lastMessage"."date", "lastMessage"."text"
FROM "contacts"
JOIN "lastMessage"
ON ("lastMessage"."senderId" = "contacts"."id")
OR ("lastMessage"."recipientId" = "contacts"."id")
WHERE "contacts"."id" != 1
ORDER BY "lastMessage"."date" DESC
很遗憾,它不起作用。
任何反馈将不胜感激!
加入 messages
到 contacts
的 2 个副本并聚合:
SELECT c2.name, MAX(m.date) last_date, m.text
FROM messages m
INNER JOIN contacts c1 ON c1.id IN (m.senderId, m.recipientId)
INNER JOIN contacts c2 ON c2.id IN (m.senderId, m.recipientId) AND c1.id <> c2.id
WHERE c1.name = ?
GROUP BY c2.id
ORDER BY last_date DESC;
将 ?
更改为您想要的联系人姓名。
参见demo。