Я довго намагався розібратися, але починаю відмовлятися.
Щоб спростити випадок, скажімо, я отримав 2 таблиці. Головний стіл є articles
і я залишився з ним contracts
. У таблиці контрактів є дата завершення. Я хочу вибрати 1 (один) рядок з кожної статті, вибравши останню contract_to
дата.
Я спробував щось подібне LEFT JOIN contracts ON (contracts.article = articles.id) ORDER BY contract_to DESC LIMIT 1
але, очевидно, він не працює.
Як мені це зробити?
Будь ласка, зробіть вигляд, що діапазони дат для кожного рядка в таблиці контрактів нижче.
Також остання дата не є однаковою для всіх контрактів на статтю, тому я не можу просто визначити, якою є остання дата, а потім вставити її у пункт WHERE.
Відповіді:
3 для відповіді № 1Отримати останню contract_to
значення, вам знадобиться a MAX()
сукупність. Правильний спосіб зробити це - використовувати підзапит об'єднати, щоб отримати тільки article
і MAX(contract_to)
Значення, потім приєднатися, що з іншими значеннями рядка. Нарешті, цілу структуру можна приєднати до articles
стіл
SELECT
articles.*,
contracts.*
FROM
articles
/* Join against a subquery which returns only the article and latest contract_to */
LEFT JOIN (
SELECT article, MAX(contract_to) AS contract_to
FROM contracts
GROUP BY article
) maxcontract ON articles.article_id = maxcontract.article
/* and join that against the rest of the contracts table, on those two column values */
JOIN contracts
ON maxcontract.article = contracts.article
AND maxcontract.contract_to = contracts.contract_to
З MySQL поблажливо ставиться до вмісту GROUP BY
пункт, цей метод може фактично не бути необхідним, приєднуючись окремо проти contracts
і ви, ймовірно, могли б зробити це з подзапросом приєднатися окремо, але це не допомогло б працювати в більшості інших СУБД, і це дійсно правильний спосіб зробити це, не покладаючись на дивне поведінку MySQL.
1 для відповіді № 2
MySQL не має приємних аналітичних функцій, які пропонують деякі СУБД для цього, але ви можете написати (наприклад):
SELECT ...
FROM articles
LEFT
OUTER
JOIN ( SELECT article,
MAX(contract_to) AS contract_to
FROM contracts
GROUP
BY article
) articles_to_max_contracts
ON articles_to_max_contracts.article = articles.id
LEFT
OUTER
JOIN contracts
ON contracts.article = articles.id
AND contracts.contract_to = articles_to_max_contracts.contract_to
;
0 для відповіді № 3
Щоб отримати лише ціну, ви можете зробити це з відповідним підзапитом:
select a.*,
(select price
from contracts c
where a.article = c.article
order by contract_from desc
limit 1
) as lastPrice
from articles a;
З індексом на contracts(article, contract_from)
це має бути навіть відносно ефективним.