web-dev-qa-db-fra.com

TSQL - Est-il possible de définir l'ordre de tri?

Est-il possible de définir un ordre de tri pour les résultats renvoyés?

J'aimerais que l'ordre de tri soit "orange", "pomme", "fraise" et non croissant ou décroissant.

Je sais que ORDER BY peut faire ASC ou DESC mais existe-t-il un type de type DEFINED ('orange', 'Apple', 'fraise')?

Cela fonctionnera sur SQL Server 2000.

22
Justin808

C'est incroyablement maladroit, mais vous pouvez utiliser une instruction CASE pour commander:

SELECT * FROM Blah 
ORDER BY CASE MyColumn 
    WHEN 'orange' THEN 1 
    WHEN 'Apple' THEN 2 
    WHEN 'strawberry' THEN 3 
    END 

Vous pouvez également créer une table secondaire contenant le champ de tri et un ordre de tri.

TargetValue  SortOrder
orange       1
Apple        2
strawberry   3

Et rejoignez votre table sur cette nouvelle table.

50
LittleBobbyTables

Utilisez une instruction CASE :

ORDER BY CASE your_col
           WHEN 'orange' THEN 1
           WHEN 'Apple' THEN 2
           WHEN 'strawberry' THEN 3
         END 

Autre syntaxe, avec un ELSE:

ORDER BY CASE 
           WHEN your_col = 'orange' THEN 1
           WHEN your_col = 'Apple' THEN 2
           WHEN your_col = 'strawberry' THEN 3
           ELSE 4
         END 
10
OMG Ponies

S'il s'agit d'une exigence de courte durée, utilisez un énoncé de cas. Toutefois, si vous pensez que cela peut durer un certain temps et que l'ordre va toujours être d'ordre orange/Apple/strawberry (ou même si ce n'est pas le cas - voir ci-dessous), vous pouvez penser à sacrifier de l'espace disque pour gagner du temps.

Créez une nouvelle colonne dans votre table appelée or_ap_st et utilisez un déclencheur d'insertion/mise à jour pour la renseigner avec le nombre 1, 2 ou 3, en fonction de la valeur de votre colonne de fruits. Puis indexez dessus.

Etant donné que le seul moment où les données de cette colonne vont changer est celui de la ligne, c'est le meilleur moment pour le faire. Le coût sera alors engagé sur un petit nombre d'écritures plutôt que sur un grand nombre de lectures, donc amorti sur les états select.

Votre requête sera alors extrêmement rapide:

select field1, field2 from table1
order by or_ap_st;

sans fonctions par ligne tuant la performance.

Et, si vous souhaitez également d'autres ordres de tri, eh bien, c'est pourquoi j'ai appelé la colonne or_ap_st. Vous pouvez ajouter autant de colonnes de tri que nécessaire.

7
paxdiablo

Ce que je fais dans ce cas c'est

ORDER BY
  CASE WHEN FRUIT = 'Orange' THEN 'A' 
       WHEN FRUIT = 'Apple' THEN 'B'
       WHEN FRUIT = 'Strawberry' THEN 'C'
       ELSE FRUIT
END
2
turtlepick

Aller plus loin de la réponse de turtlepick :

ORDER BY
  CASE WHEN FRUIT = 'Orange' THEN 'A' 
       WHEN FRUIT = 'Apple' THEN 'B'
       WHEN FRUIT = 'Strawberry' THEN 'C'
       ELSE FRUIT
  END

Si vous avez plusieurs éléments dans FRUIT et que ceux-ci commencent par des lettres définies après THEN, ces éléments apparaissent dans l'ordre codé en dur. Par exemple, Banana apparaît avant Strawberry. Vous pouvez le contourner avec

ORDER BY
  CASE
    WHEN FRUIT = 'Orange' THEN '.1'
    WHEN FRUIT = 'Apple' THEN '.2'
    WHEN FRUIT = 'Strawberry' THEN '.3'
    ELSE FRUIT
  END

Ici, j'ai utilisé des caractères avec des valeurs inférieures ASCII dans l'espoir qu'ils n'apparaissent pas au début des valeurs de FRUIT.

1
Kuitsi

Ajoutez une clé à la table (par exemple, fruit_id int identity (1,1) clé primaire) pour conserver l'ordre d'insertion.

create table fruit(fruit_id int identity(1,1) primary key, name varchar(50))
go

insert into fruit(name) values ('orange')
insert into fruit(name) values ('Apple')
insert into fruit(name) values ('strawberry')

select name from fruit

résultat:

orange
Apple
strawberry
0
The Danish

Pas aussi courant, mais pour les opérations à valeur unique ou des modèles spécifiques,REPLACEfonctionne aussi

par exemple.

DECLARE @Fruit TABLE (Fruit_Id INT IDENTITY(1, 1) PRIMARY KEY ,Name VARCHAR(50));

INSERT  INTO @Fruit (Name) VALUES  ('Orange');
INSERT  INTO @Fruit (Name) VALUES  ('Apple');
INSERT  INTO @Fruit (Name) VALUES  ('Strawberry');
INSERT  INTO @Fruit (Name) VALUES  ('__Pear');


SELECT * FROM @Fruit AS f
ORDER BY REPLACE(f.Name,'__','')



Fruit_Id    Name
----------- --------------------------------------------------
2           Apple
1           Orange
4           __Pear
3           Strawberry
0
Vland