Naturel de Tri dans MySQL
Est-il un moyen élégant d'avoir performant, tri naturel dans une base de données MySQL?
Par exemple si j'ai ce jeu de données:
- Final Fantasy
- Final Fantasy 4
- Final Fantasy 10
- Final Fantasy 12
- Final Fantasy 12: Chains of Promathia
- Final Fantasy Aventure
- Final Fantasy Origines
- Final Fantasy Tactics
Tout autre élégant solution que de diviser les noms de jeux dans leurs composantes
- Titre: "Final Fantasy"
- Nombre: "12"
- Sous-titres: "Chains of Promathia"
à assurez-vous qu'ils viennent de sortir dans le bon ordre? (10) après 4, pas avant 2).
Faire est une douleur dans le** parce que chaque maintenant et puis, il y a un autre jeu qui casse le mécanisme de l'analyse du titre du jeu (par exemple, "Warhammer 40,000", "James Bond 007")
- Chains of Promathia est de 11.
- Double Possible de MySQL 'Order By' - tri alphanumérique correctement
Vous devez vous connecter pour publier un commentaire.
Je pense que c'est pourquoi beaucoup de choses sont triés par date de sortie.
Une solution pourrait être de créer une autre colonne de votre table pour le "SortKey". Cela pourrait être une version aseptisée du titre qui est conforme à un modèle que vous créez pour faciliter le tri ou un comptoir.
Ici est une solution rapide:
SELECT alphanumeric, integer FROM sorting_test ORDER BY SOUNDEX(alphanumeric), LENGTH(alphanumeric), alphanumeric
. Si cela fonctionne, c'est parce que SOUNDEX idéalement ignore le nombre, assurant ainsi que, par exemple,apple1
vient avantz1
.alphanmuric
,length(alphanumeric)
pour éviter de "Dingo" avant de "Final Fantasy"Viens de trouver ceci:
N'naturel de tri lorsque les nombres sont à l'avant, peut travailler pour le milieu ainsi.
games
est utilisé que dans un contexte numérique et ainsi convertis à un certain nombre avant la comparaison. Si dans le milieu on se convertissent toujours à 0 et le tri sera devenu le pseudo-aléatoires.addAttributeToSort('name', ASC)
et maintenant il ressemble à ceci:addAttributeToSort('name + 0', ASC)
. Maintenant, quand j'ai les catégories de commencer avec 1 ou 2 chiffres, ils sont naturellement triés. Brillante réponse, merci pour le partage!Même fonction que posté par @plalx, mais réécrit pour MySQL:
Utilisation:
nat_name
colonne. Nous utilisons un déclencheur pour l'exécution de la fonction à chaque fois qu'une ligne est mise à jour. Cette approche vous donne tri naturel sans réel sur les performances au détriment d'une colonne supplémentaire.if ($query->orderby[0]["field"] === "node_field_data.title") { $orderBySql = " udf_NaturalSortFormat(node_field_data.title, 10, '.') "; $query->orderby = []; $query->addOrderBy(NULL, $orderBySql, $query->orderby[0]["direction"], 'title_natural'); array_unshift($query->orderby, end($query->orderby)); }
MySQL n'autorise pas ce genre de "tri naturel", donc il semble que la meilleure façon d'obtenir ce que vous êtes après est de diviser votre jeu de données comme vous l'avez décrit ci-dessus (id séparé de champ, etc), ou, à défaut, effectuer un tri basé sur un non-élément de titre, indexé en fonction de l'élément dans votre base de données (date, id inséré dans la base de données, etc).
Avoir la db de faire le tri pour vous, c'est presque toujours va être plus rapide que la lecture de grands ensembles de données dans votre langage de programmation de choix et le tri là-bas, donc si vous avez aucun contrôle sur la db schéma ici, puis regardez l'ajout de facilement triés champs comme décrit ci-dessus, il vous permettra de gagner beaucoup de tracas et de maintenance à long terme.
Demandes en vue d'ajouter un "naturel tri" de venir de temps en temps sur le MySQL bugs et les forums de discussion, et de nombreuses solutions s'articulent autour de décapage des parties de vos données et de moulage pour la
ORDER BY
partie de la requête, par exempleCe type de solution pourrait juste au sujet de travailler sur votre Final Fantasy exemple ci-dessus, mais n'est pas particulièrement flexible et peu de chances d'étendre proprement à un ensemble de données, y compris, par exemple, "Warhammer 40,000" et "James Bond 007" j'ai peur.
J'ai écrit cette fonction pour MSSQL 2000 il y a un moment:
Donc, même si je sais que vous avez trouvé une réponse satisfaisante, j'ai été aux prises avec ce problème pendant un certain temps, et nous avions déjà déterminé qu'il ne pouvait pas être fait relativement bien en SQL et que nous allions avoir à utiliser javascript sur un tableau JSON.
Voici comment je l'ai résolu simplement en utilisant SQL. Espérons que cela est utile pour les autres:
J'avais des données telles que:
En fait je n'ai pas de "fonte" des choses mais je suppose qu'qui peut également avoir travaillé.
J'ai d'abord remplacé les pièces qui sont les mêmes dans les données, dans ce cas de la "Scène ", et puis a un LPAD à la ligne des choses. Cela semble permettre assez bien pour l'alpha chaînes de trier correctement ainsi que le numéro d'chers.
Mon
ORDER BY
clause ressemble:Évidemment, ce n'est pas aider avec le problème d'origine qui n'était pas uniforme, mais j'imagine que ce serait probablement travailler pour de nombreux autres problèmes connexes, afin de le mettre là-bas.
Ajouter une Clé de Tri (Rang) de votre tableau.
ORDER BY rank
Utiliser la "Date de sortie" de la colonne.
ORDER BY release_date
Lors de l'extraction de données à partir de SQL, faites votre objet de faire le tri, par exemple, si l'extraction dans un Ensemble, d'en faire un TreeSet, et faire de votre modèle de données mettre en œuvre Comparable et de promulguer le naturel algorithme de tri ici (le tri par insertion suffira si vous utilisez une langue sans collections) comme vous le serez en lisant les lignes de SQL, un par un, comme vous créez votre modèle et l'insérer dans la collection)
Concernant la meilleure réponse de Richard Toth https://stackoverflow.com/a/12257917/4052357
Regarder pour encodés en utf-8 chaînes qui contiennent 2byte (ou plus) des caractères et des nombres par exemple
À l'aide de MySQL
LENGTH()
dansudf_NaturalSortFormat
fonction retourne la longueur en octets de la chaîne et être incorrect, utilisez plutôtCHAR_LENGTH()
qui sera de retour le caractère correct de la longueur.Dans mon cas, à l'aide de
LENGTH()
causé des requêtes de ne jamais complète, et le résultat à 100% d'utilisation du PROCESSEUR pour MySQLp.s. J'aurais ajouté ceci dans un commentaire de l'original, mais je n'ai pas assez de réputation (encore)
À l'ordre:
0
1
2
10
23
101
205
1000
un
aac
b
casdsadsa
css
Utiliser cette requête:
a1
,a2
,a11
, etc...Si vous ne voulez pas de réinventer la roue ou de maux de tête avec beaucoup de code qui ne fonctionne pas, il suffit d'utiliser Drupal Naturel De Tri ... il suffit d'exécuter le SQL qui vient zippé (MySQL ou Postgre), et c'est tout. Lors d'une requête, il suffit de commander à l'aide de:
Une autre option est de faire le tri dans la mémoire après avoir retiré les données de mysql. Bien que ce ne sera pas la meilleure option du point de vue des performances, si vous n'êtes pas le tri des listes énormes vous devriez être bien.
Si vous jetez un oeil à Jeff post, vous pouvez trouver de nombreux algorithmes pour ce que jamais la langue vous pouvez travailler avec.
De tri pour les êtres Humains : Naturel, l'Ordre de Tri
Ajouter un champ "clé de tri" qui a toutes les chaînes de chiffres complété par des zéros à une longueur fixe et de faire le tri sur le champ à la place.
Si vous avez de longues chaînes de chiffres, une autre méthode est d'ajouter le nombre de chiffres (en largeur fixe, des zéros) pour chaque chaîne de chiffres. Par exemple, si vous n'avez pas plus de 99 chiffres dans une rangée, puis pour le "Super Blast 10 Ultra" de la clé de tri serait "Super Blast 0210 Ultra".
Vous pouvez également créer de façon dynamique, la "colonne de tri" :
De cette façon, vous pouvez créer des groupes pour trier.
Dans ma requête, je voulais que le " - " à la face de tout, puis les nombres, puis le texte. Qui pourrait en résulter quelque chose comme :
De cette façon, vous n'avez pas à maintenir la colonne de tri dans l'ordre correct lorsque vous ajoutez des données. Vous pouvez également modifier l'ordre de tri en fonction de ce que vous avez besoin.
J'ai essayé plusieurs solutions, mais la réalité c'est très simple:
23-4244
. Merci 🙂z_99
là et il va se mettre au top maisz
vient aprèsv
.Si vous êtes à l'aide de PHP, vous pouvez faire de la naturel de tri en php.
J'espère que MySQL va mettre en œuvre tri naturel dans une future version, mais la demande de fonctionnalité (#1588) est ouvert depuis 2003, je ne voudrais pas retenir mon souffle.
Simplifié de la non-udf version de la meilleure réponse de @plaix/Richard Toth/Luc Hoggett, qui ne fonctionne que pour le premier entier dans le domaine, est
Il y a aussi natsort. Il est destiné à être une partie d'un drupal plug-in, mais il fonctionne très autonome.
Je sais que ce sujet est ancien mais je crois que j'ai trouvé un moyen de le faire:
La ferraille, il a trié les suivantes mal réglé (C'est inutile lol):
Final Fantasy 1
Final Fantasy 2
Final Fantasy 5
Final Fantasy 7
Final Fantasy 7: Advent Children
Final Fantasy 12
Final Fantasy 112
FF1
FF2