2013-03-10 170 views
3

我不知道這是我在一個很長的一天的後端,或者我已經得到了編碼器等效的編寫器塊,但我想不出一個乾淨的方式做到這一點。Tricky where子句

我有一個存儲網頁菜單結構的表,我想要一個簡單的存儲過程,它將根據Web應用程序中的會話參數返回相關的菜單項。

採取以下的(簡化的)例子:

--#### 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. 頁面ID 3只應列出如果@IsLoggedIn = 1@IsAdmin = 1
  3. 頁面ID 4應該一直列出除非@IsLoggedIn = 1(有可能是需要登錄用戶(甚至管理員用戶)但仍然需要隱藏的頁面 - 這是我的大腦爆炸的位... )
  4. 頁ID 5應該是可見的所有的時間,無論用戶是否登錄或沒有,如果他們是管理員或不是因爲它不要求用戶名和它不是隱藏登錄用戶
+0

你可以給樣品記錄以表格的形式? – 2013-03-10 22:10:39

+2

我個人更喜歡你給它的格式。使得設置一個SQL小提琴更容易。 – 2013-03-10 22:20:58

+0

關於#3,如果頁面同時設置了RequireLogin和HideIfLoggedIn,這是否意味着它應該被排除在外,而不管@ IsLoggedIn的值?或者一種偏好優先於另一種? – 2013-03-11 00:01:40

回答

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 for @IsLoggedIn = 1, IsAdmin = 1 - PageID2,3,5顯示。

SQL Fiddle for @IsLoggedIn = 0, IsAdmin = 1 - PageID4,5顯示。

+0

非常接近 - 做得很好,但是我忘記了我的示例中最常見的情況,當RequireLogin = 0且RequireAdmin = 0且HideIfLoggedIn = 0時,這表示任何人都應該看到 - 登錄或不需要的東西,我需要調整答案也要考慮到這一點。 - 我修訂我的問題,包括這個場景(頁ID 5) - 編號有興趣看看你會如何解決這個:) – HeavenCore 2013-03-10 23:25:56

+0

OK,更新;由於這種新的情況並沒有真正匹配其餘的邏輯(尤其是* @ IsLoggedIn *),我認爲最簡單的做法是在最後添加一個最後一個檢查來捕獲特定的組合。所有更新的示例現在都可以使用讓我知道事情的後續。 – 2013-03-10 23:59:32

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

我認爲這有更好的可讀性當where子句圍繞負結構...

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