2013-03-10 8 views
3

Я не знаю, если я нахожусь на заднем конце очень длинного дня или у меня есть кодер, эквивалентный сценаристам, но я не могу придумать, как это сделать.Tricky where clause

У меня есть таблица, в которой хранится структура меню веб-страниц, и я хочу, чтобы простая хранимая процедура возвращала соответствующие пункты меню на основе параметров сеанса в веб-приложении.

Рассмотрим следующий (упрощенный) пример:

--#### 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 

Для приведенного примера данных, следующие потребности, чтобы быть правдой:

  1. страницы ID 2 должны быть перечислены только если @IsLoggedIn = 1
  2. Идентификатор страницы 3 следует указывать только в том случае, если @IsLoggedIn = 1И@IsAdmin = 1
  3. Идентификатор страницы 4 должен быть указан постоянно UNLESS@IsLoggedIn = 1 (могут быть страницы, для которых требуется зарегистрированный пользователь (и даже пользователь admin), но все же нужно скрывать - это бит, где мой мозг взрывается ...)
  4. Page ID 5 должны быть видны все время, независимо, если пользователь вошел в систему или нет, и если они являются администратором или нет, поскольку он не требует логина и оно не скрыто для зарегистрированных пользователей
+0

вы можете дать записи образца в табличном формате? –

+2

Я лично предпочитаю формат, который вы ему дали. Делает упрощение настройки SQL-скрипта. –

+0

Что касается № 3, если на странице есть как 'RequireLogin', так и' HideIfLoggedIn', это означает, что это должно быть исключено независимо от значения '@ IsLoggedIn'? Или одно предпочтение имеет приоритет над другим? –

ответ

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

Работы для меня.

Редактировать после комментария:

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) 

Я обновил запрос, чтобы поймать ваше последнее требование, и обновляется следующий SQL скрипках:

SQL Fiddle для @IsLoggedIn = 1, IsAdmin = 0 - PageID2,5 отображается.

SQL Fiddle для @IsLoggedIn = 1, IsAdmin = 1 - PageID2,3,5 отображается.

SQL Fiddle для @IsLoggedIn = 0, IsAdmin = 1 - PageID4,5 отображается.

+0

Очень близко - хорошо сделано, однако я пропустил самое обычное явление из моего примера, когда RequireLogin = 0 AND RequireAdmin = 0 AND HideIfLoggedIn = 0 указывает на то, что должно быть видимым для кого угодно - вошел в систему или нет, мне нужно настроить ответьте, чтобы принять это во внимание.- Я пересмотрел свой вопрос, чтобы включить этот сценарий (идентификатор страницы 5) - id будет интересно посмотреть, как вы справитесь с этим :) – HeavenCore

+0

ОК, обновлено; так как этот новый случай на самом деле не соответствует остальной логике (в частности, * @ IsLoggedIn *), я думаю, что самое простое - добавить последнюю проверку в конце, чтобы зафиксировать конкретную комбинацию. Все обновленные примеры теперь работают; дайте мне знать, как это происходит. –

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

Я думаю, что это имеет лучшую читаемость, когда, где положение структурировано вокруг негатива ...

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) 
    )