/ / ORDER BY і LIMIT 1 в приєднаній таблиці - mysql, join

ORDER BY і LIMIT 1 у приєднаній таблиці - mysql, join

Я довго намагався розібратися, але починаю відмовлятися.

Щоб спростити випадок, скажімо, я отримав 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) це має бути навіть відносно ефективним.