Ceci est une ancienne révision du document !
Quand on veut extraire d'une base SQL des informations texte triées en utilisant 'ORDER BY', on se heurte au problème habituel: l'ordre de tri coïncide avec l'ordre des caractères dans les polices de caractères, c'est à dire, par exemple, que:
Pour trier selon l'alphabet français, et en fait, selon l'alphabet qu'on veut, on va créer une fonction de comparaison comme cmp(v1, v2), c'est à dire qui compare v1 et v2 et qui renvoie:
Ceci, comme on peut le faire avec la méthode sort() du Python v2.x.
Prenons la fonction de comparaison qu'on a déjà sur une autre page de ce site (http://python.jpvweb.com/mesrecettespython/doku.php?id=tris_alpha). On va seulement la modifier dans son titre (compalpha) et dans son encodage (comparaison en 'utf-8' et pas en unicode) :
def compalpha(v1,v2): """comparaison des chaines de caractères v1 et v2: renvoie un entier <0 si v1<v2, 0 si v1==v2, un entier >0 si v1>v2 v1, v2 doivent être en utf-8 """ alpha = ur"""!"#$%&'()*+,-./0123456789:;<=>?@""" + \ ur"""[\]^_`""" + \ ur"""{|}~ €""" + \ ur"""aAàÀâÂæÆbBcCçÇdDeEéÉèÈêÊëËfFgGhHiIîÎïÏjJkKlLmMnNoOôÔœŒpPqQrRsStTuUùÙûÛüÜvVwWxXyYÿŸzZ""" alpha = alpha.encode('utf-8') lgalpha = len(alpha) lg1 = len(v1) lg2 = len(v2) lg = min([lg1,lg2]) # on veut lg=longueur du mot le plus court entre V1 et v2 for i in range(0,lg): i1 = alpha.find(v1[i]) if i1<0: i1 = lgalpha + ord(v1[i]) i2 = alpha.find(v2[i]) if i2<0: i2 = lgalpha + ord(v2[i]) if i1<i2: return -1 if i1>i2: return 1 # ici, les lg premiers caractères sont identiques: le mot le plus court est avant l'autre return lg1-lg2
Le principe est simple: c'est vous qui donnez l'ordre de tri avec la définition de la variable alpha. Et les caractères non inclus dans cette variable sont situés après, avec pour indice, l'ordre qu'ils ont dans la police de caractères.
Prenons maintenant un exemple: on crée une base sqlite3 contenant une table “test” avec un champ “nom” contenant dans l'ordre d'introduction:
xabc abcç abcé Xabcù Abcè
Voilà le code pour extraire ces données et les présenter dans l'ordre de tri habituel:
cur.execute("SELECT nom FROM test ORDER BY nom") datas = cur.fetchall() for data in datas: print data[0]
Ce qui donne à l'exécution:
Abcè Xabcù abcç abcé xabc
Vous constatez que ce n'est pas terrible: le 'a' est bien ici après le 'X'…
Voilà maintenant le code qui permet de trier dans le bon ordre:
cnx.create_collation("compalpha", compalpha) cur.execute("SELECT nom FROM test ORDER BY nom COLLATE compalpha") datas = cur.fetchall() for data in datas: print data[0]
Ce qui affiche:
abcç abcé Abcè xabc Xabcù
C'est quand même autre chose, non?
Amusez-vous bien!