Резюме: У меня есть форум с таблицей forums
таблицей posts
. Каждый пост имеет уникальный идентификатор (целое число с автоматическим добавлением), и каждое сообщение ссылается на forums.id
.
Я пытаюсь выдать запрос SELECT
который извлекает все имена форума, все идентификаторы форума, а затем самые высокие posts.id
связанные с этим форумом.
Возможно, что в форуме нет сообщений, и в этом случае я хочу, чтобы max-posts-id был 0.
Таблица форумов:
| ID | Name |
|----|------|
| 1 | Dogs |
| 2 | Food |
| 3 | Work |
Стол сообщений:
| ID | Forum_ID | Author | Text |
|----|----------|--------|------|
| 42 | 1 | Mr. S | foo |
| 43 | 3 | Mr. Y | bar |
| 44 | 1 | Ms. X | baz |
| 45 | 2 | Ms. A | foo |
| 46 | 1 | Mr. M | foo |
| 47 | 3 | Ms. A | bar |
| 48 | 2 | Mr. L | baz |
Желаемый результат:
| Forum_ID | Name | Max_Posts_ID |
|----------|------|--------------|
| 1 | Dogs | 46 |
| 2 | Food | 48 |
| 3 | Work | 47 |
Моя попытка
SELECT
forums.id AS id,
forums.name AS name,
COALESCE(MAX(SELECT id FROM posts WHERE forums.id = ?), 0)
JOIN
posts ON forums.id = posts.forum_id;
Но я не думаю, что могу передать параметр моему вложенному запросу SELECT
, я не думаю, что это правильный подход. Что мне делать вместо этого?
Вы можете использовать LEFT JOIN
и агрегацию:
SELECT f.id AS id,
f.name AS name,
COALESCE(MAX(p.id),0) AS Max_Posts_ID
FROM Forums f
LEFT JOIN Posts p
ON f.Id = p.forum_id
GROUP BY f.id, f.name
ORDER BY f.id;
Решение вашей проблемы:
MySQL
SELECT fs.id AS Forum_ID ,
fs.name AS Name,
IFNULL(MAX(ps.ID),0) AS Max_Posts_ID
FROM forums fs
LEFT JOIN posts ps
ON fs.id = ps.forum_id
GROUP BY fs.id,fs.name;
Ссылка на демоверсию MySQL:
MSSQL
SELECT fs.id AS Forum_ID ,
fs.name AS Name,
ISNULL(MAX(ps.ID),0) AS Max_Posts_ID
FROM forums fs
LEFT JOIN posts ps
ON fs.id = ps.forum_id
GROUP BY fs.id,fs.name;
Ссылка на демонстрацию MSSQL:
ВЫХОД:
Forum_ID Name Max_Posts_ID
1 Dogs 46
2 Food 48
3 Work 47
Ссылка на код: http://tpcg.io/pI2HO5
BEGIN TRANSACTION;
/* Create a table called NAMES */
CREATE TABLE Forums (Id integer PRIMARY KEY, Name text);
/* Create few records in this table */
INSERT INTO Forums VALUES(1,'Dogs');
INSERT INTO Forums VALUES(2,'Food');
INSERT INTO Forums VALUES(3,'Work');
/* Create a table called NAMES */
CREATE TABLE Posts (Id integer PRIMARY KEY, forId integer);
/* Create few records in this table */
INSERT INTO Posts VALUES(42,1);
INSERT INTO Posts VALUES(43,3);
INSERT INTO Posts VALUES(64,1);
INSERT INTO Posts VALUES(45,2);
INSERT INTO Posts VALUES(46,1);
INSERT INTO Posts VALUES(47,3);
INSERT INTO Posts VALUES(48,2);
INSERT INTO Posts VALUES(51,2);
COMMIT;
/* Display all the records from the table */
SELECT Distinct forId as Forum_Id, Posts.id, (Select Name from Forums where forId == Forums.id) FROM Posts,Forums GROUP BY Posts.forId;
Output :
1|64|Dogs
2|51|Food
3|47|Work
Позвольте мне исправить вашу текущую попытку с подзапросом корреляции
SELECT
id AS id,
name AS name,
(SELECT COALESCE(MAX(ID), 0) FROM Posts where forum_id = f.Id) AS Max_Posts_ID
FROM Forums f
Исправления:
from
пунктаid
столбца запроса с Posts
forum_id
COALESCE()
- это ANSI SQL,IFNULL()
- нет.)