У вашому рішенні використовується розширення на пункт GROUP BY, яке дозволяє групувати за деякими полями (у даному випадку просто post_author
):
GROUP BY wp_posts.post_author
та виберіть неагреговані стовпці:
SELECT wp_posts.*
які не вказані в групі за допомогою пункту або не використовуються в сукупній функції (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 завжди вибирає перший рядок, з яким він стикається, ви правильно сортуєте рядки перед групою 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