Question

Il doit exister un meilleur moyen d'écrire cette requête.

Je veux sélectionner toutes les données entre deux dates. Idéalement, les première et dernière lignes du jeu de résultats seraient celles spécifiées dans la clause WHERE. Si ces lignes n'existent pas, je veux les lignes précédant et suivant la plage demandée.

Un exemple:

Si mes données sont:

...
135321, 20090311 10:15:00
135321, 20090311 10:45:00
135321, 20090311 11:00:00
135321, 20090311 11:15:00
135321, 20090311 11:30:00
135321, 20090311 12:30:00
...

Et la requête est:

    SELECT * 
    FROM data_bahf 
    WHERE param_id = 135321 
    AND datetime >= '20090311 10:30:00' 
    AND datetime <= '20090311 12:00:00'

Je souhaite que les données renvoyées incluent la ligne à 10h15 et celle de 12h30. Pas seulement ceux qui respectent strictement la clause WHERE.

C’est le meilleur que j’ai trouvé.

SELECT * FROM (
    SELECT * 
    FROM data_bahf 
    WHERE param_id = 135321 
    AND datetime > '20090311 10:30:00' 
    AND datetime < '20090311 12:00:00'

    UNION

    (
        SELECT * FROM data_bahf 
        WHERE param_id = 135321 
        AND datetime <= '20090311 10:30:00' 
        ORDER BY datetime desc
        LIMIT 1
    )

    UNION

    (
        SELECT * FROM data_bahf 
        WHERE param_id = 135321 
        AND datetime >= '20090311 12:00:00'
        ORDER BY datetime asc
        LIMIT 1
    )
) 
AS A
ORDER BY datetime

(Ignorez l'utilisation de SELECT * pour l'instant)

EDIT: J'ai des index sur param_id, datetime et (param_id, datetime)

Était-ce utile?

La solution

Tout d'abord, assurez-vous de disposer d'un index composite sur (id_param, date / heure)

Deuxièmement, utilisez la requête suivante:

SELECT  *
FROM    data_bahf
WHERE   param_id = 135321
        AND datetime BETWEEN
        COALESCE(
        (
        SELECT  MAX(datetime)
        FROM    data_bahf
        WHERE   param_id = 135321
              AND datetime <= '2009-01-01 00:00:00'
        ), '0001-01-01')
        AND 
        COALESCE(
        (
        SELECT  MIN(datetime)
        FROM    data_bahf
        WHERE   param_id = 135321
              AND datetime >= '2009-01-02 00:00:00'
        ), '9999-01-01')

Vient de cocher, il est exécuté dans 1.215 ms pour un exemple de tableau de 200 000 lignes

.

Autres conseils

Je dirais ceci:

SELECT 
  o.* 
FROM 
  data_bahf o
WHERE 
  o.param_id = 135321 
  AND o.datetime BETWEEN
  ISNULL(
    (
      SELECT   MAX(datetime) 
      FROM     data_bahf i
      WHERE    i.param_id = 135321 AND i.datetime <= '20090311 10:30:00'
    ),
    '0001-01-01 00:00:00'
  )
  AND
  ISNULL(
    (
      SELECT   MIN(datetime) 
      FROM     data_bahf i
      WHERE    i.param_id = 135321 AND i.datetime >= '20090311 12:00:00'
    ),
    '9999-12-31 23:59:59'
  )

EDIT: Fallback ajouté.
Lorsqu'il n'y a pas de ligne correspondant à la sous-requête, il en résulte une valeur NULL , qui doit être interceptée par ISNULL () ou le BETWEEN L'opérateur échouera et la requête principale ne renverra aucune ligne.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top