2009-12-28 11 views
1

J'ai une table avec les colonnes City et ZoneCode. J'ai une liste déroulante où je peux sélectionner une seule ville ou tout. Et une autre liste déroulante pour le ZoneCode. Fondamentalement, ce sont des filtres qui ne filtrent que si je sélectionne une valeur dans les listes déroulantes.Recherche de filtre

Y at-il une technique recommandée pour ce faire?

edit: cette table n'est qu'un exemple.

Merci

Répondre

2

Si vous avez un indice composite sur (City, ZoneCode):

SELECT * 
FROM mytable 
WHERE City = @City 
     AND ZoneCode = @ZoneCode 
UNION ALL 
SELECT * 
FROM mytable 
WHERE City = @City 
     AND @ZoneCode IS NULL 
UNION ALL 
SELECT * 
FROM mytable 
WHERE @City IS NULL 
     AND @ZoneCode IS NULL 

Si vous ne l'avez pas et ne peut pas créer:

SELECT * 
FROM mytable 
WHERE City = COALESCE(@City, City) 
     AND ZoneCode = COALESCE(@ZoneCode, ZoneCode) 

La première requête suppose que vous ne pouvez pas filtrer ZoneCode sans en spécifiant le City.

+0

Coalesce! Cela fonctionne parfaitement! Y a-t-il un désavantage en utilisant la coalescence? –

+0

En supposant que vous avez un index, vous finirez avec un balayage d'index au lieu d'une recherche d'index. C'est pourquoi vous devriez normaliser. – Aaronaught

+0

'@Artur Carvalho': Ce n'est pas sargable, c'est-à-dire que l'index ne peut pas être utilisé pour chercher quand l'expression est dans' COALESCE'. Cela nécessitera un scan complet de la table ce qui est bien si vous n'avez pas d'index composite, mais sera plus lent si vous en avez un. Dans ce dernier cas, la première requête sera plus rapide. – Quassnoi

3

Puisque vous avez balisé ce que sql-server, je vais supposer que vous êtes à la recherche des recommandations du côté de la base de données, par opposition à la façon de le faire dans le front- fin.

Ma recommandation est: Normaliser. Si un ZoneCode appartient à une ville particulière, alors vous devriez avoir une table de villes et une table de ZoneCodes, avec votre table de client (ou n'importe quelle table a ces colonnes maintenant) faisant référence à un ZoneCodeID.

schéma Exemple:

CREATE TABLE Cities 
(
    CityID int NOT NULL IDENTITY(1, 1) 
     CONSTRAINT PK_Cities PRIMARY KEY CLUSTERED, 
    CityName varchar(100) NOT NULL 
) 

CREATE INDEX IX_Cities_Name 
ON Cities (CityName) 

CREATE TABLE ZoneCodes 
(
    ZoneCodeID int NOT NULL IDENTITY(1, 1) 
     CONSTRAINT PK_ZoneCodes PRIMARY KEY CLUSTERED, 
    CityID int NOT NULL 
     CONSTRAINT FK_ZoneCodes_Cities FOREIGN KEY 
      REFERENCES Cities (CityID) 
       ON UPDATE NO ACTION, 
       ON DELETE NO ACTION 
    ZoneCode varchar(10) NOT NULL 
) 

CREATE INDEX IX_ZoneCodes_City 
ON ZoneCodes (CityID) 
INCLUDE (ZoneCode) 

Pour filtrer c'est aussi simple que:

SELECT ZoneCodeID, ZoneCode 
FROM ZoneCodes 
WHERE (@CityID IS NULL) OR (CityID = @CityID) 

Ou, si vous avez seulement le nom:

SELECT z.ZoneCodeID, z.ZoneCode 
FROM ZoneCodes z 
INNER JOIN Cities c 
ON c.CityID = z.CityID 
WHERE (@CityName IS NULL) OR (CityName = @CityName) 

Si vous ne pouvez pas faites cela - c'est-à-dire parce que ce sont des données de forme libre, ou parce que les personnes de saisie de données peuvent w la ville, mais pas le ZoneCode, etc., alors tout ce que je peux suggérer, est de vous assurer que vous êtes indexé correctement:

CREATE INDEX IX_MyTable_City_ZoneCode 
ON MyTable (City) 
INCLUDE (ZoneCode) 

Ensuite, votre filtre doit être:

SELECT DISTINCT ZoneCode 
FROM MyTable 
WHERE (@City IS NULL) OR (City = @City) 

... à obtenir les ZoneCodes pour une ville, et:

SELECT FirstColumn, SecondColumn, ... 
FROM MyTable 
WHERE ((@City IS NULL) OR (City = @City)) 
AND ((@ZoneCode IS NULL) OR (ZoneCode = @ZoneCode)) 
1

Conditions WHERE clauses dans TSQL sont assez moche. Je construisais différentes requêtes pour chaque condition et exécutais la requête appropriée en fonction de l'entrée de l'utilisateur.

+0

Pourquoi sont-ils mauvais? Je suppose que la coalescence est l'une de ces clauses conditionnelles. Merci pour la réponse Will. –

Questions connexes