J'ai une simple requête SQL dans PostgreSQL 8.3 qui attrape un tas de commentaires. Je fournis une liste triée de valeurs à la IN
construction dans la WHERE
clause:
SELECT * FROM comments WHERE (comments.id IN (1,3,2,4));
Cela renvoie des commentaires dans un ordre arbitraire qui, dans mon cas, est des identifiants similaires 1,2,3,4
.
Je veux que les lignes résultantes triées comme la liste dans la IN
construction: (1,3,2,4)
.
Comment y parvenir?
sql
postgresql
sql-order-by
sql-in
casse Noisette
la source
la source
Réponses:
Vous pouvez le faire assez facilement avec (introduit dans PostgreSQL 8.2) VALUES (), ().
La syntaxe sera comme ceci:
la source
with ordered_products as (select row_number() OVER (ORDER BY whatever) as reportingorder, id from comments) ... ORDER BY reportingorder
.Simplement parce qu'il est si difficile à trouver et qu'il doit être diffusé: dans mySQL, cela peut être fait beaucoup plus simplement, mais je ne sais pas si cela fonctionne dans d'autres SQL.
la source
ERROR: cannot pass more than 100 arguments to a function
Dans Postgres 9.4 ou version ultérieure, c'est probablement le plus simple et le plus rapide :
En utilisant le nouveau
WITH ORDINALITY
, que @a_horse a déjà mentionné .Nous n'avons pas besoin d'une sous-requête, nous pouvons utiliser la fonction de retour de jeu comme une table.
Une chaîne littérale à remettre dans le tableau au lieu d'un constructeur ARRAY peut être plus facile à implémenter avec certains clients.
Explication détaillée:
la source
Je pense que cette façon est meilleure:
la source
... order by id=? desc, id=? desc, id=? desc
et cela semble fonctionnerAvec Postgres 9.4, cela peut être fait un peu plus court:
Ou un peu plus compact sans table dérivée:
Suppression de la nécessité d'attribuer / maintenir manuellement une position à chaque valeur.
Avec Postgres 9.6, cela peut être fait en utilisant
array_position()
:Le CTE est utilisé de sorte que la liste de valeurs ne doit être spécifiée qu'une seule fois. Si ce n'est pas important, cela peut également être écrit comme suit:
la source
IN
liste de laWHERE
clause dans laORDER BY
clause, ce qui en fait la meilleure réponse à mon humble avis ... Maintenant, seulement pour trouver quelque chose de similaire pour MySQL ...order by array_position(array[42,48,43], c.id::int);
ce qui peut conduire à des bogues dans certains cas.array_position(array[42, 48, 43]::bigint[], c.id::bigint)
, donc pas besoin de tronquerbigint
àint
.Une autre façon de le faire dans Postgres serait d'utiliser la
idx
fonction.N'oubliez pas de créer d'abord la
idx
fonction, comme décrit ici: http://wiki.postgresql.org/wiki/Array_Indexla source
CREATE EXTENSION intarray;
.enable_extension
vous permettra de l'activer tant que l'utilisateur de votre application est membre durds_superuser
groupe.Dans Postgresql:
la source
position(id::text in '123,345,3,678')
. L'identifiant3
correspondra avant l'identifiant345
, n'est-ce pas?En recherchant un peu plus cela, j'ai trouvé cette solution:
Cependant, cela semble plutôt verbeux et peut avoir des problèmes de performances avec de grands ensembles de données. Quelqu'un peut-il commenter ces questions?
la source
IN
clause? parce que je dois le faire pour des milliers de disques.Pour ce faire, je pense que vous devriez probablement avoir une table "ORDER" supplémentaire qui définit le mappage des identifiants à commander (faisant effectivement ce que votre réponse à votre propre question a dit), que vous pouvez ensuite utiliser comme colonne supplémentaire sur votre sélection vous pouvez ensuite trier.
De cette façon, vous décrivez explicitement l'ordre que vous désirez dans la base de données, là où il devrait être.
la source
sans SEQUENCE, fonctionne uniquement sur 8.4:
la source
ou si vous préférez le mal au bien:
la source
Et voici une autre solution qui fonctionne et utilise une table constante ( http://www.postgresql.org/docs/8.3/interactive/sql-values.html ):
Mais encore une fois, je ne suis pas sûr que ce soit performant.
J'ai un tas de réponses maintenant. Puis-je avoir des votes et des commentaires pour savoir qui est le gagnant!
Merci a tous :-)
la source
[ÉDITER]
unnest n'est pas encore intégré à 8.3, mais vous pouvez en créer un vous-même (la beauté de n'importe quel *):
cette fonction peut fonctionner dans n'importe quel type:
la source
Légère amélioration par rapport à la version qui utilise une séquence je pense:
la source
ici, [bbs] est la table principale qui a un champ appelé ids, et, ids est le tableau qui stocke le comments.id.
passé dans postgresql 9.6
la source
Permet d'avoir une impression visuelle de ce qui a déjà été dit. Par exemple, vous avez une table avec certaines tâches:
Et vous souhaitez classer la liste des tâches en fonction de son statut. Le statut est une liste de valeurs de chaîne:
L'astuce consiste à donner à chaque valeur de statut un entier et à ordonner la liste numérique:
Qui conduit à:
Crédit @ user80168
la source
Je suis d'accord avec toutes les autres affiches qui disent "ne faites pas ça" ou "SQL n'est pas bon pour ça". Si vous souhaitez trier selon une facette de commentaires, ajoutez une autre colonne entière à l'une de vos tables pour contenir vos critères de tri et trier par cette valeur. par exemple "ORDER BY comments.sort DESC" Si vous voulez les trier dans un ordre différent à chaque fois, alors ... SQL ne sera pas pour vous dans ce cas.
la source