2017-10-21 12 views
0

Je donne rank à chaque ligne par son create_time dans les instances de table par groupe (task_id, task_time) comme key.I My SQL primaire est comme suitmysql `having` opération avec une valeur @variable spécifique

SELECT 
task_id, 
task_time, 
create_time, 
@rn := CASE WHEN @prev_task_id <> task_id THEN 1 
     WHEN @prev_task_time <> task_time THEN 1 
     ELSE @rn + 1 END AS rank, 
@prev_task_id := task_id, 
@prev_task_time := task_time 
FROM instances, (SELECT 
        @rn := 0, 
        @prev_task_id := -1, 
        @prev_task_time := '-1') t 
where task_id in (1209, 1211) 
having rank = 1 
ORDER BY task_id, task_time DESC, create_time DESC; 

Question vient Après j'ajoute la clause having rank = 1. Le résultat retourné n'est pas précis par rapport au résultat sans having rank = 1 et il manque des enregistrements dont le rang est également 1, par exemple, la plupart des enregistrements avec task_id = 1211 sont manquants. Comme je sais, having clause est lancée après select pour ajouter un filtre aux enregistrements finaux. Je veux savoir les erreurs que j'ai faites, THX.

+0

Essayez de mettre "groupBy rank" avant l'avoir. –

+0

Pourquoi utilisez-vous 'having'? Lisez à ce sujet. Il faudra implicitement 'grouper par' toutes les colonnes et si vous définissez sql_mode = 'only_full_group_by'' ou si vous utilisez 5.7+, on vous dira que vous utilisez un comportement non standard car cela n'a pas de sens de 'sélectionner' une colonne non groupée sur. Quoi que vous voulez, cette requête ne le fait pas. – philipxy

+0

Copie possible de https://stackoverflow.com/q/34115174/3404097 – philipxy

Répondre

0

MySQL ne garantit pas l'ordre d'évaluation des expressions dans un select. Ainsi, vous ne pouvez pas assigner une variable et l'utiliser ensuite dans une autre expression - et vous attendre à faire ce que vous voulez.

Je recommande une sous-requête:

SELECT x.* 
FROM (SELECT task_id, task_time, create_time, 
       (@rn := (CASE WHEN @p = concat_ws(':', task_id, task_time) THEN 1 
          WHEN @p := concat_ws(':', task_id, task_time) THEN @rn + 1 
          ELSE @rn + 1 
         END) 
      ) AS rank, 
     FROM instances CROSS JOIN 
      (SELECT @rn := 0, @p := '') params 
     WHERE task_id in (1209, 1211) 
     ORDER BY task_id, task_time DESC, create_time DESC; 
    ) x 
WHERE rank = 1 ; 

Notes:

  • Dans les versions les plus récentes de MySQL, vous avez besoin d'un sous-requête. ORDER BY ne fonctionne pas avec les variables sans la sous-requête.
  • MySQL ne garantit pas l'ordre d'exécution des expressions dans un SELECT, vous devez donc effectuer toutes les affectations dans une sous-requête.
  • Vous pouvez combiner l'expression qui définit les groupes en une seule variable.
+0

Merci pour votre aide! Votre sql fonctionne bien (bien que quelques petites erreurs dedans). En outre, je me demande pourquoi le fait d'avoir ne fonctionne pas. Que ce soit comme le dit le commentaire, c'est parce que mon paramétrage de mysql ne regroupe pas implicitement toutes les colonnes et devient un comportement indéfini. –