Это довольно сложно сделать в SQL вообще;вы, вероятно, не сможете сделать это через ORM.
Вы не можете использовать GROUP BY для этого.Это используется для указания SQL, как группировать элементы для агрегации, а это не то, что вы здесь делаете.«SELECT x, y FROM таблицы GROUP BY x» является недопустимым SQL, поскольку значение y не имеет смысла.
Давайте рассмотрим это с ясной схемой:
CREATE TABLE objects ( id INTEGER PRIMARY KEY, name VARCHAR );
CREATE TABLE comments ( object_id INTEGER REFERENCES objects (id), text VARCHAR NOT NULL, date TIMESTAMP NOT NULL );
INSERT INTO objects (id, name) VALUES (1, 'object 1'), (2, 'object 2');
INSERT INTO comments (object_id, text, date) VALUES
(1, 'object 1 comment 1', '2010-01-02'),
(1, 'object 1 comment 2', '2010-01-05'),
(2, 'object 2 comment 1', '2010-01-08'),
(2, 'object 2 comment 2', '2010-01-09');
SELECT * FROM objects o JOIN comments c ON (o.id = c.object_id);
Самый элегантный способ, который я когда-либо видел, это оконные функции Postgresql 8.4.
SELECT * FROM (
SELECT
o.*, c.*,
rank() OVER (PARTITION BY object_id ORDER BY date DESC) AS r
FROM objects o JOIN comments c ON (o.id = c.object_id)
) AS s
WHERE r = 1;
, который выберет первый комментарий для каждого объекта по дате, самый новый сначала.Если вы не видите, что это делает, выполните внутренний SELECT самостоятельно и посмотрите, как он генерирует rank (), что делает его довольно простым.
Я знаю другие способы сделать это с Postgresql, ноЯ не знаю, как это сделать в других базах данных.
Попытка вычислить это динамически может привести к серьезным головным болям - и для того, чтобы эти сложные запросы работали хорошо, требуется больше работы.Скорее всего, вам лучше сделать это простым способом: сохраните поле last_comment_id
для каждого объекта и обновите его, когда комментарий будет добавлен или удален, так что вы можете просто присоединиться и отсортировать.Возможно, вы могли бы использовать триггеры SQL для автоматической обработки этого обновления.