2009-11-22 6 views
0

J'ai une tableTrouver les données les plus proches de la date?

CREATE TABLE `symbol_details` (
    `symbol_header_id` int(11) DEFAULT NULL, 
    `DATE` datetime DEFAULT NULL, 
    `ADJ_NAV` double DEFAULT NULL 
) 

avec 20.000.000 entrées ~. Maintenant, je veux trouver la valeur ADJ_NAV plus proche de la fin du trimestre pour un seul symbol_header_id:

SET @quarterend = '2009-3-31'; 

SELECT symbol_header_id AS she, ADJ_NAV AS aend FROM symbol_details 
WHERE 
symbol_header_id = 18546 
AND DATE= (
# date closest after quarter end 
SELECT DATE FROM symbol_details 
WHERE ABS(DATEDIFF(DATE, @quarterend)) < 10 
AND DATE<[email protected] 
AND symbol_header_id = 18546 
ORDER BY ABS(DATEDIFF(DATE, @quarterend)) ASC LIMIT 1) 

Quand je lance l'intérieur « sélectionnez la date » requête retourne rapidement. Exécuter simplement la requête externe avec la date correcte remplie à la place de la sous-requête se termine également très rapidement. Mais quand je cours la chose entière cela prend pour toujours - quelque chose ne va pas?

+0

Avez-vous un indice à la date ainsi que symbol_header_id? – Donnie

+0

Je fais. Un sur date et un sur symbol_header_id et la date plus un sur symbol_header_id. Est-ce que cela change la façon dont ils interrogent est évalué? –

Répondre

1

Vous pouvez probablement faire sans la sous-requête. Il suffit de saisir la première ligne:

SELECT * 
FROM symbol_details 
WHERE DATE <= @quarterend 
AND symbol_header_id = 18546 
ORDER BY DATE DESC 
LIMIT 1 
+0

C'est vrai, mais le problème est que s'il n'y a pas de données pour ce trimestre, cela retournera des données vraiment anciennes. Mais je pourrais juste ajouter ET date> @quarterstart ... Laissez-moi essayer cela. Merci beaucoup pour la réponse !! –

+0

Ceci est génial et m'a amené à la solution, voir ma diatribe dans le post original en cours, mais j'ai dû changer cela en groupe par pour obtenir toutes les valeurs. Mais maintenant il y a un autre problème ... –

+0

@Martin Stein: Je ne suis même pas sûr de ce que fait 'GROUP BY symbol_header_id DESC', donc je le demanderais dans une nouvelle question – Andomar

2

Il semble que l'optimiseur a quelques problèmes pour évaluer correctement la déclaration et trouver le plan le plus efficace. (Dans Oracle, je vous demanderais de mettre à jour les statistiques, mais je ne suis pas sûr de savoir comment l'optimiseur fonctionne dans MySQL.)

Je voudrais essayer d'autres façons d'exprimer votre déclaration pour voir ce qui est le plus logique l'optimiseur:

  • connecter explicitement les deux symbol_header_ids du immer et la requête externe
  • essayer un SELECT max(date) .. au lieu du « Trier par Limite 1 »
  • essayer de faire une jointure réflexive de symbol_details

J'espère qu'il y a une idée utile ici.

1

Essayez:

SELECT t.symbol_header_id, 
      COALESCE(t.adj_nav, '0.0') 'adj_nav' 
    FROM SYMBOL_DETAILS t 
LEFT JOIN (SELECT sh.symbol_header_id, 
        MAX(sh.date) 'max_date' 
      FROM SYMBOL_DETAILS sh 
      WHERE ABS(DATEDIFF(sh.date, @quarter_end)) < 10 
       AND sh.date <= @quarter_end) x ON x.symbol_header_id = t.symbol_header_id 
              AND x.max_date = t.date 
    WHERE t.symbol_header_id = 18546