2013-03-10 4 views
3

Je ne sais pas si c'est moi à l'arrière d'une très longue journée ou j'ai les codeurs équivalents de blocs d'écrivains, mais je ne peux pas penser à une façon propre de le faire.Tricky où la clause

J'ai une table qui stocke une structure de menu de pages Web, et je veux une procédure stockée simple qui renverra les articles de menu appropriés basés sur les paramètres de session dans l'application Web.

Prenons l'exemple suivant (simplifié):

--#### Create example table 
CREATE TABLE [dbo].[tbl_Page](
    [PageID] [int] IDENTITY(1,1) NOT NULL, 
    [RequireLogin] [bit] NOT NULL, 
    [RequireAdmin] [bit] NOT NULL, 
    [HideIfLoggedIn] [bit] NOT NULL 
) 
GO 

--#### Insert Dummy Data 
SET IDENTITY_INSERT [dbo].[tbl_Page] ON 
INSERT [dbo].[tbl_Page] ([PageID], [RequireLogin], [RequireAdmin], [HideIfLoggedIn]) VALUES (2, 1, 0, 0) 
INSERT [dbo].[tbl_Page] ([PageID], [RequireLogin], [RequireAdmin], [HideIfLoggedIn]) VALUES (3, 1, 1, 0) 
INSERT [dbo].[tbl_Page] ([PageID], [RequireLogin], [RequireAdmin], [HideIfLoggedIn]) VALUES (4, 0, 0, 1) 
INSERT [dbo].[tbl_Page] ([PageID], [RequireLogin], [RequireAdmin], [HideIfLoggedIn]) VALUES (5, 0, 0, 0) 
SET IDENTITY_INSERT [dbo].[tbl_Page] OFF 

--#### Create menu procedure 
CREATE PROCEDURE usp_GetSubMenu 
    @ParentID INT , 
    @IsLoggedIn BIT , 
    @IsAdmin BIT 
AS 
    BEGIN 
     SET NOCOUNT ON; 

     SELECT PageID , 
       RequireLogin , 
       RequireAdmin , 
       HideIfLoggedIn 
     FROM tbl_Page 
     WHERE ???????????? 
    END 
GO 

Pour les données d'exemple données, les besoins suivants pour être vrai:

  1. page ID 2 ne devrait être énuméré si @IsLoggedIn = 1
  2. L'ID de page 3 ne doit être répertorié que si @IsLoggedIn = 1ET@IsAdmin = 1
  3. L'ID de page 4 doit être répertorié en permanence SAUF@IsLoggedIn = 1 (il se peut qu'il y ait des pages nécessitant un utilisateur connecté (et même un utilisateur administrateur), mais qui doivent encore se cacher - c'est le peu où mon cerveau explose ...)
  4. page ID 5 doit être visible tout le temps, peu importe si l'utilisateur est connecté ou non et si elles sont un administrateur ou non, car il ne nécessite pas de connexion et il isnt caché pour les utilisateurs connectés
+0

peut vous donner des enregistrements d'échantillons sous forme de tableau? –

+2

Personnellement, je préfère le format dans lequel vous l'avez donné. Rend la mise en place d'un fiddle SQL plus facile. –

+0

En ce qui concerne le numéro 3, si une page contient à la fois les ensembles 'RequireLogin' et' HideIfLoggedIn', cela signifie-t-il qu'elle devrait être exclue indépendamment de la valeur de '@ IsLoggedIn'? Ou est-ce qu'une préférence a préséance sur l'autre? –

Répondre

2
select PageID, 
    RequireLogin, 
    RequireAdmin, 
    HideIfLoggedIn 
from tbl_Page 
where (HideIfLoggedIn <> @IsLoggedIn) 
    and (RequireLogin = 0 or @IsLoggedIn = 1) 
    and (RequireAdmin = 0 or @IsAdmin = 1) 

Fonctionne pour moi.

Modifier après commentaire:

select PageID, 
    RequireLogin, 
    RequireAdmin, 
    HideIfLoggedIn 
from tbl_Page 
where ((HideIfLoggedIn <> @IsLoggedIn) 
    and (RequireLogin = 0 or @IsLoggedIn = 1) 
    and (RequireAdmin = 0 or @IsAdmin = 1)) 
    or (RequireLogin = 0 and RequireAdmin = 0 and HideIfLoggedIn = 0) 

J'ai mis à jour la requête pour reprendre votre dernière exigence, et mis à jour le Fiddles SQL suivante:

SQL Fiddle pour @IsLoggedIn = 1, IsAdmin = 0-PageID2,5 affiché.

SQL Fiddle pour @IsLoggedIn = 1, IsAdmin = 1-PageID2,3,5 affiché.

SQL Fiddle pour @IsLoggedIn = 0, IsAdmin = 1-PageID4,5 affiché.

+0

Très proche - bien fait, mais j'ai manqué l'occurrence la plus commune de mon exemple, lorsque RequireLogin = 0 ET RequireAdmin = 0 ET HideIfLoggedIn = 0 cela indique quelque chose qui devrait être visible à tout le monde - connecté ou non, je dois ajuster répondez pour en tenir compte aussi.- J'ai révisé ma question pour inclure ce scénario (ID de page 5) - soyez intéressé de voir comment vous aborderiez ceci :) – HeavenCore

+0

OK, mis à jour; Puisque ce nouveau cas ne correspond pas vraiment au reste de la logique (en particulier * @ IsLoggedIn *), je pense que la chose la plus simple à faire est d'ajouter une dernière vérification à la fin pour capturer la combinaison particulière. Tous les exemples mis à jour fonctionnent maintenant; laissez-moi savoir comment ça se passe. –

1
SELECT PageID , 
      RequireLogin , 
      RequireAdmin , 
      HideIfLoggedIn 
    FROM tbl_Page 
    WHERE 
    (@IsLoggedIn = 1 AND [HideIfLoggedIn] = 0) 
    AND [RequireLogin] = @IsLoggedIn 
    AND [RequireAdmin] = @IsAdmin   
1

Je pense que cela a une meilleure lisibilité lorsque la clause where est structuré autour du négatif ...

SELECT 
    PageID, 
    RequireLogin, 
    RequireAdmin, 
    HideIfLoggedIn 
FROM 
    tbl_Page 
WHERE 
    NOT 
    (
     (HideIfLoggedIn = 1 AND @IsLoggedIn = 1) 
     OR (RequireLogin = 1 AND @IsLoggedIn = 0) 
     OR (RequireAdmin = 1 AND @IsAdmin = 0) 
    )