Ваше решение использует расширение предложения GROUP BY , которое позволяет группировать по некоторым полям (в данном случае просто post_author
):
GROUP BY wp_posts.post_author
и выберите неагрегированные столбцы:
SELECT wp_posts.*
которые не перечислены в предложении group by или которые не используются в статистической функции (MIN, MAX, COUNT и т. д.).
Правильное использование расширения для предложения GROUP BY
Это полезно, когда все значения неагрегированных столбцов равны для каждой строки.
Например, предположим, у вас есть стол GardensFlowers
( name
сада, flower
который растет в саду):
INSERT INTO GardensFlowers VALUES
('Central Park', 'Magnolia'),
('Hyde Park', 'Tulip'),
('Gardens By The Bay', 'Peony'),
('Gardens By The Bay', 'Cherry Blossom');
и вы хотите извлечь все цветы, которые растут в саду, где растут несколько цветов. Затем вы должны использовать подзапрос, например, вы можете использовать это:
SELECT GardensFlowers.*
FROM GardensFlowers
WHERE name IN (SELECT name
FROM GardensFlowers
GROUP BY name
HAVING COUNT(DISTINCT flower)>1);
Если вам нужно извлечь все цветы, которые являются единственными цветами в гардере, вы можете просто изменить условие HAVING на HAVING COUNT(DISTINCT flower)=1
, но MySql также позволяет вам использовать это:
SELECT GardensFlowers.*
FROM GardensFlowers
GROUP BY name
HAVING COUNT(DISTINCT flower)=1;
нет подзапроса, не стандартный SQL, но проще.
Неправильное использование расширения для предложения GROUP BY
Но что произойдет, если вы выберете неагрегированные столбцы, которые не равны для каждой строки? Какое значение выбирает MySql для этого столбца?
Похоже, что MySql всегда выбирает первое значение, с которым сталкивается.
Чтобы убедиться, что первое значение, с которым оно сталкивается, является именно тем значением, которое вы хотите, вам нужно применить a GROUP BY
к упорядоченному запросу, следовательно, необходимо использовать подзапрос. Вы не можете сделать это иначе.
Учитывая предположение, что MySql всегда выбирает первую встреченную строку, вы корректно сортируете строки перед GROUP BY. Но, к сожалению, если вы внимательно прочитаете документацию, вы заметите, что это предположение неверно.
При выборе неагрегированных столбцов, которые не всегда одинаковы, MySql может выбрать любое значение, поэтому результирующее значение, которое он фактически показывает, является неопределенным .
Я вижу, что этот прием для получения первого значения неагрегированного столбца часто используется, и он обычно / почти всегда работает, иногда я тоже его использую (на свой страх и риск). Но поскольку это не задокументировано, вы не можете полагаться на это поведение.
Эта ссылка (спасибо ypercube!), Трюк GROUP BY был оптимизирован, показывает ситуацию, в которой один и тот же запрос возвращает разные результаты между MySql и MariaDB, возможно, из-за другого механизма оптимизации.
Так что, если этот трюк сработает, это просто вопрос удачи.
Общепринятый ответ на другой вопрос выглядит не так со мной:
HAVING wp_posts.post_date = MAX(wp_posts.post_date)
wp_posts.post_date
является неагрегированным столбцом, и его значение будет официально не определено, но, скорее всего, оно будет первым post_date
. Но поскольку трюк GROUP BY применяется к неупорядоченной таблице, он не уверен, какой из них post_date
встречается первым .
Вероятно, он вернет сообщения, которые являются единственными публикациями одного автора, но даже это не всегда точно.
Возможное решение
Я думаю, что это может быть возможным решением:
SELECT wp_posts.*
FROM wp_posts
WHERE id IN (
SELECT max(id)
FROM wp_posts
WHERE (post_author, post_date) = (
SELECT post_author, max(post_date)
FROM wp_posts
WHERE wp_posts.post_status='publish'
AND wp_posts.post_type='post'
GROUP BY post_author
) AND wp_posts.post_status='publish'
AND wp_posts.post_type='post'
GROUP BY post_author
)
На внутренний запрос я возвращаю максимальную дату публикации для каждого автора. Затем я принимаю во внимание тот факт, что один и тот же автор теоретически может иметь две записи одновременно, поэтому я получаю только максимальный идентификатор. А потом я возвращаю все строки, которые имеют эти максимальные идентификаторы. Это можно сделать быстрее, используя соединения вместо предложения IN.
(Если вы уверены, что ID
это только увеличивается, и если это ID1 > ID2
также означает post_date1 > post_date2
, что запрос можно сделать намного проще, но я не уверен, что это так).
post_author
иpost_date
не достаточно, чтобы получить уникальный ряд, поэтому должно быть больше, чтобы получить уникальный ряд дляpost_author