PG:: Error: SELECT DISTINCT, les expressions ORDER BY doivent apparaître dans la liste select

Actionview::Template::Error (PG:: Error: ERROR: pour SELECT DISTINCT, les expressions ORDER BY doivent apparaître dans la liste select

Je crée un site web d'événements et j'essaie de trier les RSVP rendus par l'Heure de début de l'événement. Il y a beaucoup de RSVP donc je les regroupe avec distinct, mais j'ai eu beaucoup de difficulté au cours des derniers jours sur le tri des résultats sans que cette erreur n'apparaisse sur PG. J'ai regardé quelques-unes des questions précédentes sur l' sujet et je suis encore assez perdu. Comment puis-je obtenir que cela fonctionne? Merci beaucoup!

@rsvps = Rsvp.where(:voter_id => current_user.following.collect {|f| f["id"]}, :status => 'going').where("start_time > ? AND start_time < ?", Time.now, Time.now + 1.month).order("count_all desc").count(:group => :event_id).collect { |f| f[0] }

<%= render :partial => 'rsvps/rsvp', :collection => Rsvp.where(:event_id => @rsvps).select("DISTINCT(event_id)").order('start_time asc') %>
30
demandé sur Tomasz Jakub Rup 2012-10-02 19:11:12

2 réponses

La clause ORDER BY ne peut être appliquée que Après que le DISTINCT a été appliqué. Étant donné que seuls les champs de L'instruction SELECT sont pris en compte pour les opérations distinctes, ce sont les seuls champs qui peuvent être utilisés dans ORDER BY.

Logiquement, si vous voulez juste une liste distincte de valeurs event_id, l'ordre dans lequel elles se produisent devrait être hors de propos. Si l'ordre compte, vous devez ajouter le start_time à la liste de sélection afin qu'il y ait un contexte pour le ordre.

En outre, ces deux clauses SELECT ne sont pas équivalentes, alors faites attention:

SELECT DISTINCT(event_id, start_time) FROM ...

SELECT DISTINCT event_id, start_time FROM ...

La seconde est la forme que vous voulez. Le premier retournera une série d'enregistrements avec les données représentées comme une construction de ligne (une seule colonne avec un tuple à l'intérieur). La seconde retournera des colonnes normales de sortie de données. Cela ne fonctionne que comme prévu dans le cas d'une seule colonne où la construction de ligne est réduite car il ne s'agit que d'une seule colonne.

35
répondu Matthew Wood 2012-10-02 15:25:14

Je sais que c'est une question plutôt ancienne, mais je viens de passer par un petit exemple dans ma tête qui m'a aidé à comprendre pourquoi Postgres a cette restriction apparemment étrange sur SELECT DISTINCT / ORDER BY columns.

Imaginez que vous avez les données suivantes dans votre table Rsvp:

 event_id |        start_time
----------+------------------------
    0     | Mar 17, 2013  12:00:00
    1     |  Jan 1, 1970  00:00:00
    1     | Aug 21, 2013  16:30:00
    2     |  Jun 9, 2012  08:45:00

Maintenant, vous voulez récupérer une liste d'event_ids distincts, Classés par leurs start_times respectifs. Mais où devrait aller 1? Devrait-il venir en premier, parce que le tuple commence le 1er janvier 1970, ou devrait-il aller dernier à cause du 21 août 2013?

Comme le système de base de données ne peut pas prendre cette décision pour vous et que la syntaxe de la requête ne peut pas dépendre des données réelles sur lesquelles elle peut fonctionner (en supposant que event_id est unique), nous sommes limités à la commande uniquement par colonnes de la clause SELECT.

En ce qui concerne la question réelle - une alternative à la réponse de Matthew utilise une fonction d'agrégat comme MIN ou MAX pour le tri:

  SELECT event_id
    FROM Rsvp
GROUP BY event_id
ORDER BY MIN(start_time)

Le regroupement et l'agrégation explicites sur start_time permis la base de données pour trouver un ordre sans ambiguïté des tuples de résultat. Notez cependant que la lisibilité est définitivement un problème dans ce cas;)

51
répondu AdrianoKF 2013-08-22 14:11:01