2010-12-02 5 views
5

J'ai récemment ajouté deux champs à certaines tables de ma base de données (SQL Server 2005) pour permettre aux utilisateurs de personnaliser l'ordre de tri des lignes. J'ai suivi ce modèle pour toutes les tables:Définition d'un champ d'ordre de tri basé sur l'ordre alphabétique d'un autre champ

-- Alter the InvoiceStatus table 
ALTER TABLE [dbo].[InvoiceStatus] ADD [Disabled] bit NOT NULL DEFAULT 0 
GO 
ALTER TABLE [dbo].[InvoiceStatus] ADD [SortOrder] int NOT NULL DEFAULT 0 
GO 
-- Use the primary key as the default sort order 
UPDATE [dbo].[InvoiceStatus] 
    SET [SortOrder] = [InvoiceStatusId] 
GO 

Normalement, comme vous pouvez le voir, je l'ai utilisé la clé primaire comme l'ordre de tri par défaut. Maintenant, je suis cependant dans la situation que je voudrais utiliser l'ordre alphabétique d'un champ de texte dans la table comme l'ordre de tri par défaut. En utilisant le tableau ci-dessus comme un exemple (qui a un champ de texte [InvoiceStatusName]), y a-t-il une requête simple et courte que je pourrais écrire pour utiliser l'ordre alphabétique de [InvoiceStatusName] comme ordre de tri par défaut?

Mise à jour:
La question est déjà répondu, mais certains a fait remarquer que cette solution pourrait ne pas être idéal donc je veux juste ajouter un peu de contexte pour de futures références. C'est un vieux système (pas vieux-vieux, mais il a été autour pendant quelques années) en usage une poignée d'endroits différents.

Il existe plusieurs listes/menus déroulants dans l'application avec votre type « d'état » typique (comme d'état de la facture, état de la commande, type de client etc.). Au moment de la première écriture du système, ces valeurs étaient utilisées dans tous les endroits (pas de modification), mais certains utilisateurs ont commencé à demander la possibilité d'ajouter de nouveaux statuts, de supprimer ceux qui ne sont plus utilisés et de spécifier un ordre de tri (un statut peut être plus fréquemment utilisé, et il est donc agréable de l'avoir en haut de la liste). Le moyen le plus simple que j'ai trouvé pour faire cela (sans avoir à se tromper avec trop de l'ancien code) était d'ajouter deux nouveaux champs, Disabled et SortOrder, à toutes les tables pertinentes. Le champ Disabled est utilisé pour "masquer" les types non utilisés (impossible de les supprimer en raison de l'intégrité référentielle et la valeur qu'ils contiennent doit également être conservée), et le champ SortOrder est là pour que les utilisateurs puissent spécifier leur propre tri personnalisé. commande. Puisque toutes les tables pertinentes partagent également ces deux mêmes colonnes, il était très facile de créer une interface simple pour gérer le tri (et la désactivation) d'une manière générique.

Répondre

6
;WITH so AS 
(
SELECT 
    SortOrder, 
    ROW_NUMBER() OVER (ORDER BY InvoiceStatusName) AS rn 
FROM dbo.InvoiceStatus 
) 
UPDATE so SET SortOrder = rn 
+1

+1 thx Martin. J'ai appris quelque chose de nouveau aujourd'hui. * btw, vous pouvez supprimer la colonne InvoiceStatusID. * –

+0

Merci à Martin et Lieven. Vos deux suggestions sont bonnes, mais j'ai choisi Martin comme le accepté parce qu'il avait l'apparence la plus propre. – Nailuj

3

Vous pouvez utiliser la fonction ROW_NUMBER() pour mapper le nom trié sur un entier.

UPDATE dbo.InvoiceStatus 
SET  SortOrder = ivsn.Number 
FROM dbo.InvoiceStatus ivs 
     INNER JOIN (
      SELECT dbo.InvoiceStatusID 
       , [number] = ROW_NUMBER() OVER (ORDER BY InvoiceStatusName) 
      FROM dbo.InvoiceStatus 
     ) ivsn ON ivsn.InvoiceStatusID = ivs.InvoiceStatusID 

Vous devriez vous demander si, si ce régime est la meilleure solution pour votre problème. La mise en œuvre telle qu'elle est n'est pas bien adaptée.

+0

Vous n'avez pas besoin d'une jointure automatique pour cela. –

+0

@Martin: Je réfléchissais à cela mais je n'arrivais pas à comprendre comment l'écrire * sans * l'auto-jointure. Si vous créez une nouvelle réponse sans l'auto-jointure, je la modifierais. –

+0

@Lieven - Terminé! Vous pouvez mettre à jour l'expression de la table elle-même. (fonctionne avec CTE ou table dérivée) –

1

La manière dont vous avez choisi d'implémenter le tri des tables est inhabituelle et semble limitée au tri uniquement par les entiers. Vraiment, je vous recommande de revoir la conception de votre sous-système de tri d'une autre manière.

par exemple avoir une table méta-données quelque part qui contient le nom de la colonne que les utilisateurs veulent trier par, puis utiliser ORDER BY (columnname) sur les requêtes pertinentes

modifier: Oh attendez, nous parlons des tables de consultation et laisser les utilisateurs changer l'ordre. Maintenant, j'ai compris que votre implémentation est beaucoup plus logique pour moi.

+0

Jolies mises à jour, Martin et Lieven. Je suis le grincheux à cette fête, évidemment. – codeulike

+0

Cela ne m'a pas semblé grincheux et pour ce que ça vaut, je pense aussi que OP voudra changer de design pour répondre aux futures demandes. –

+0

Mon intention n'est pas de permettre aux utilisateurs de choisir la colonne à laquelle la table doit être commandée. Ils devraient être en mesure de contrôler l'ordre de tri réel des lignes (utilisé pour la présentation dans l'application). – Nailuj

Questions connexes