2017-03-15 2 views
1

Scénario: J'ai un champ char (nom: priorité) dans ma table où les valeurs sont stockées en tant que 1,2,3 et vide ("").Spécification de la valeur de départ du tri/tri à partir du milieu - Progression ouverte

for each mytable no-lock by priority: 

Cette requête est triée dans l'ordre suivant: vide, 1,2,3.

for each mytable no-lock by priority desc: 

Et, cette requête trie les enregistrements comme ceci: 3,2,1 et vide.

Mais j'ai besoin de trier les enregistrements comme ceci: 1,2,3 puis vide. Dans l'ordre croissant, mais en ignorant le blanc et en commençant à partir de 1. Y a-t-il un moyen de résoudre ce problème dans Progress?

Répondre

2

Puisque vous utilisez un champ de caractères, il traite les nombres comme des chaînes. Les valeurs ASCII pour les chaînes "1", "2" et "3" sont 49, 50 et 51. Progress traite un blanc ("") comme ASCII -1. C'est pourquoi le blanc vient en premier. La meilleure solution serait d'utiliser deux instructions FOR EACH. Tout d'abord faire les dossiers non vides:

FOR EACH mytable NO-LOCK WHERE mytable.priority <> "" BY priority: 

Ensuite, faites les enregistrements vides:

FOR EACH mytable NO-LOCK WHERE mytable.priority = "": 

Si vous avez votre logique métier dans les procédures/fonctions, vous pouvez exécuter ceux à l'intérieur des boucles FOR EACH pour éviter toute duplication de code.

+0

Cela fait à peu près tout. Assurez-vous que la priorité est indexée pour une performance maximale. – bupereira

+0

@bupereira En fait, je ne pense pas que l'indice aura de l'importance. Du moins pas pour le premier FOR EACH: le <> déclenchera une recherche table-scan/index complet. – Jensd

+0

@TheDrooper C'est une bonne suggestion. En fait, dans mon cas, la requête utilisée n'est pas si courte et simple et j'ai besoin de tout le résultat à la fois – Mahesh

1

Si (si seulement) il n'y a pas beaucoup d'enregistrements dans la table, vous pouvez peut-être copier les enregistrements dans une table temporaire avec une nouvelle priorité et trier la table temporaire à la place?

Si vous avez un million d'enregistrements, ce n'est peut-être pas le cas! Ensuite, je considérerais simplement l'ajout d'un nouveau champ.

DEFINE TEMP-TABLE MyTable NO-UNDO 
    FIELD priority AS CHARACTER 
    FIELD txt  AS CHARACTER. 

CREATE MyTable. 
ASSIGN MyTable.priority = "1" 
     MyTable.txt  = "First?". 

CREATE MyTable. 
ASSIGN MyTable.priority = "" 
     MyTable.txt  = "Last?". 

DEFINE TEMP-TABLE ttMyTable NO-UNDO LIKE MyTable 
    FIELD newPriority AS INTEGER 
    INDEX sortOrder newPriority. 

FOR EACH MyTable NO-LOCK: 
    CREATE ttMyTable. 
    BUFFER-COPY MyTable TO ttMyTable 
     ASSIGN 
      ttMyTable.newPriority = IF MyTable.priority = "" THEN 99999 ELSE INTEGER(MyTable.priority). 
END. 

FOR EACH ttMyTable NO-LOCK BY ttMyTable.newPriority: 
    DISPLAY ttMyTable. 
END. 
+0

En fait, j'utilise une requête dynamique parce que la requête doit être préparée en fonction des paramètres de recherche fournis, je ne pense pas que ce soit possible, n'est-ce pas? – Mahesh

1

Puisque vous numérisez/tous/dossiers de toute façon, vous pouvez trier dans le PAR:

define temp-table tt no-undo 
    field priority as character 
    . 

create tt. tt.priority = "". 
create tt. tt.priority = "1". 
create tt. tt.priority = "2". 
create tt. tt.priority = "3". 
create tt. tt.priority = "". 

for each tt by (if tt.priority = "" then "4" else tt.priority): 

    display string(rowid(tt)) tt.priority. 

end.