/ / ORDER BY i LIMIT 1 w złączonej tabeli - mysql, join

ORDER BY i LIMIT 1 w złączonej tabeli - mysql, join

Od dawna próbuję to rozgryźć, ale zaczynam się poddawać.

Aby uprościć sprawę, powiedzmy, że mam 2 tabele. Główny stół to articles i pozostaję przy dołączaniu do tego contracts. Tabela umów ma datę końcową. Chcę tylko wybrać 1 (jeden) wiersz z tego artykułu, wybierając najnowszy contract_to data.

Próbowałem już spróbować czegoś takiego LEFT JOIN contracts ON (contracts.article = articles.id) ORDER BY contract_to DESC LIMIT 1 ale oczywiście to nie działa.

Jak mam to zrobić?

Należy udawać, że zakresy dat dla każdego wiersza w poniższej tabeli są różne.
Również ostatnia data nie jest taka sama dla wszystkich umów na artykuły, więc nie mogę po prostu określić, co jest najnowszą datą, a następnie umieścić ją w klauzuli WHERE.

wprowadź opis obrazu tutaj

Odpowiedzi:

3 dla odpowiedzi № 1

Aby uzyskać najnowsze contract_to wartość, będziesz potrzebować MAX() agregat. Właściwym sposobem na to jest użycie sprzężenia podkwerendy, aby uzyskać tylko article i MAX(contract_to) wartości, a następnie połącz je z pozostałymi wartościami wiersza. Wreszcie, całą strukturę można połączyć z articles stół.

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

Ponieważ MySQL jest łagodny w stosunku do zawartości GROUP BY klauzula ta metoda może nie być konieczna, łącząc się oddzielnie z contracts table, i prawdopodobnie mógłbyś to zrobić z samym podzapytaniem, ale to nie zadziałało w większości innych RDBMS i jest to naprawdę dobry sposób na zrobienie tego bez polegania na dziwnym zachowaniu MySQL.


1 dla odpowiedzi nr 2

MySQL nie ma ładnych funkcji analitycznych, które oferują niektóre systemy DBMS, ale możesz napisać (na przykład):

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 dla odpowiedzi № 3

Aby uzyskać tylko cenę, możesz to zrobić również ze skorelowanym podzapytaniem:

select a.*,
(select price
from contracts c
where a.article = c.article
order by contract_from desc
limit 1
) as lastPrice
from articles a;

Z indeksem na contracts(article, contract_from) powinno to być nawet względnie wydajne.