Je me demande s'il existe un moyen (peut-être un meilleur moyen) de classer par ordre des valeurs dans une clause IN ().
Le problème est que j'ai 2 requêtes, une qui obtient tous les identifiants et la seconde qui récupère toutes les informations. Le premier crée l'ordre des ID par lesquels je veux que le second trie. Les ID sont placés dans une clause IN () dans le bon ordre.
Ce serait donc quelque chose comme (extrêmement simplifié):
SELECT id FROM table1 WHERE ... ORDER BY display_order, name
SELECT name, description, ... WHERE id IN ([id's from first])
Le problème est que la deuxième requête ne renvoie pas les résultats dans le même ordre que les ID sont placés dans la clause IN ().
Une solution que j'ai trouvée est de mettre tous les ID dans une table temporaire avec un champ à incrémentation automatique qui est ensuite joint à la deuxième requête.
Y a-t-il une meilleure option?
Remarque: Comme la première requête est exécutée «par l'utilisateur» et la seconde est exécutée dans un processus d'arrière-plan, il n'y a aucun moyen de combiner la requête 2 en 1 à l'aide de sous-requêtes.
J'utilise MySQL, mais je pense qu'il pourrait être utile de noter les options disponibles pour les autres bases de données.
la source
IN
et lesFIELD
paramètres sont égaux. Faire cela dans un code de programme peut être plus rapide en utilisant ces connaissances supplémentaires. Bien sûr, il pourrait être plus sage de placer cette charge sur le client plutôt que sur le serveur si vous avez à l'esprit les performances du serveur.sqlite
?Voir ci-dessous comment obtenir des données triées.
la source
Deux solutions qui me viennent à l'esprit:
order by case id when 123 then 1 when 456 then 2 else null end asc
order by instr(','||id||',',',123,456,') asc
(
instr()
vient d'Oracle; peut-être que vous avezlocate()
oucharindex()
ou quelque chose comme ça)la source
Ans pour obtenir des données triées.
la source
Si vous souhaitez effectuer un tri arbitraire sur une requête en utilisant des valeurs entrées par la requête dans MS SQL Server 2008+ , cela peut être fait en créant une table à la volée et en effectuant une jointure comme celle-ci (en utilisant la nomenclature d'OP).
Si vous remplacez l'instruction VALUES par quelque chose d'autre qui fait la même chose, mais en ANSI SQL, cela devrait fonctionner sur n'importe quelle base de données SQL.
Remarque: La deuxième colonne de la table créée (orderTbl.orderIdx) est nécessaire lors de l'interrogation de jeux d'enregistrements supérieurs à 100 environ. À l'origine, je n'avais pas de colonne orderIdx, mais j'ai trouvé qu'avec des ensembles de résultats supérieurs à 100, je devais trier explicitement par cette colonne; dans SQL Server Express 2014 de toute façon.
la source
orderTbl.orderKey
,orderTbl.orderIndex
parorderKey
,orderIndex
a très bien fonctionné
la source
La clause IN décrit un ensemble de valeurs et les ensembles n'ont pas d'ordre.
Votre solution avec une jointure puis un classement sur la
display_order
colonne est la solution la plus correcte; tout le reste est probablement un hack spécifique au SGBD (ou fait des choses avec les fonctions OLAP en SQL standard). Certes, la jointure est la solution la plus portable (bien que la génération des données avec lesdisplay_order
valeurs puisse être problématique). Notez que vous devrez peut-être sélectionner les colonnes de classement; c'était une exigence dans SQL standard, bien que je pense que cela a été assoupli il y a quelque temps (peut-être aussi longtemps que SQL-92).la source
Utilisez la fonction MySQL FIND_IN_SET :
la source
Pour Oracle, la solution de John utilisant la fonction instr () fonctionne. Voici une solution légèrement différente qui a fonctionné -
SELECT id FROM table1 WHERE id IN (1, 20, 45, 60) ORDER BY instr('1, 20, 45, 60', id)
la source
J'ai juste essayé de faire cela avec MS SQL Server où nous n'avons pas FIELD ():
Notez que j'autorise également la duplication.
la source
Ma première pensée a été d'écrire une seule requête, mais vous avez dit que ce n'était pas possible car l'une est exécutée par l'utilisateur et l'autre est exécutée en arrière-plan. Comment stockez-vous la liste des identifiants à passer de l'utilisateur au processus d'arrière-plan? Pourquoi ne pas les mettre dans une table temporaire avec une colonne pour signifier la commande.
Alors que diriez-vous de ceci:
la source
Je pense que vous devriez réussir à stocker vos données de manière à ce que vous fassiez simplement une jointure et ce sera parfait, donc pas de hacks et de choses compliquées.
J'ai par exemple une liste "Récemment jouée" des identifiants de piste, sur SQLite je fais simplement:
la source
Essayez ceci:
Les WHERE nécessiteront probablement un petit ajustement pour que les sous-requêtes corrélées fonctionnent correctement, mais le principe de base doit être sain.
la source