J'ai une association 1: m.
symbols
table a plusieurs lignes dans company_key_statistics
table. company_key_statistics
a la colonne createdAt
qui est l'horodatage indiquant quand la ligne a été créée. Je dois rejoindre la dernière symbols
avec company_key_statistics
, mais je n'ai besoin que des dernières company_key_statistics
. Par exemple, je dois obtenir ORCL
et MSFT
symbols
et uniquement leur dernière company_key_statistics
.
Jusqu'à présent, j'ai essayé cela.
SELECT `symbols`.`id`,
`symbols`.`symbol`,
`statistics`.
`marketCapitalization`
FROM `symbols`
LEFT JOIN (SELECT `s`.`companyId`,
`s`.`marketCapitalization`
FROM `company_key_statistics` AS `s`
WHERE `s`.`companyId` = `symbols`.`id`
ORDER by `createdAt`
DESC LIMIT 1) AS `statistics`
ON `symbols`.`id` = `statistics`.`companyId`
WHERE `symbols`.`symbol` IN ('ORCL', 'SNAP');
Mais malheureusement, j'ai trouvé que je ne peux pas utiliser les colonnes de la requête parent dans les sous-requêtes JOIN
.
Comment puis-je y parvenir?
Essaye ça:
SELECT sym.id, sym.symbol, s.marketCapitalization
FROM symbols AS sym
INNER JOIN company_key_statistics AS s
ON sym.id = s.companyId
INNER JOIN (SELECT companyId, MAX(createdAt) AS createdAt
FROM company_key_statistics
GROUP BY companyId) AS smax
ON smax.companyId = s.companyId AND smax.createdAt = s.createdAt
WHERE sym.symbol IN ('ORCL','SNAP');
Étant donné que votre exemple publié était un LEFT JOIN
, vous souhaitez peut-être également des entreprises sans données de capitalisation boursière dans votre réponse. Dans ce cas, nous devons imbriquer les sous-sélections, de cette façon:
SELECT sym.id, sym.symbol, s.marketCapitalization
FROM symbols AS sym
LEFT JOIN (SELECT *
FROM company_key_statistics
INNER JOIN (SELECT companyId, MAX(createdAt) AS createdAt
FROM company_key_statistics
GROUP BY companyId) AS smax
USING (companyId, createdAt)) AS s
ON sym.id = s.companyId
WHERE sym.symbol IN ('ORCL','SNAP');
Le problème général que nous abordons ici est appelé maximum par groupe et de nombreuses réponses SO et DBA.SE le traitent). Vérifiez celui-ci par exemple.
Pour une sous-requête corrélée, vous devez utiliser un CROSS APPLY, malheureusement MySql ne le permet pas, mais vous pouvez le simuler de cette façon:
SELECT `symbols`.`id`,
`symbols`.`symbol`,
`statistics`.
`marketCapitalization`,
`s`.`companyId`,
`s`.`marketCapitalization`
FROM `symbols`
INNER JOIN `company_key_statistics` `s`
ON `s`.`pk` = (SELECT `pk` -- the PK of company_key_statistics
FROM `company_key_statistics`
WHERE `companyId` = `symbols`.`id`
ORDER by `createdAt`
DESC LIMIT 1)
WHERE `symbols`.`symbol` IN ('ORCL', 'SNAP');
Vous pouvez trouver un exemple sur DONC .