Sql 棘手的where子句

Sql 棘手的where子句,sql,sql-server,sql-server-2008,tsql,Sql,Sql Server,Sql Server 2008,Tsql,我不知道是我在漫长的一天中处于后台,还是我有着与编剧相当的程序员,但我想不出一个干净的方法来做到这一点 我有一个存储web页面菜单结构的表,我想要一个简单的存储过程,它将根据web应用程序中的会话参数返回相关的菜单项 以以下简化示例为例: --#### Create example table CREATE TABLE [dbo].[tbl_Page]( [PageID] [int] IDENTITY(1,1) NOT NULL, [RequireLogin] [bit] NOT

我不知道是我在漫长的一天中处于后台,还是我有着与编剧相当的程序员,但我想不出一个干净的方法来做到这一点

我有一个存储web页面菜单结构的表,我想要一个简单的存储过程,它将根据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
对于给定的示例数据,需要满足以下条件:

仅当@IsLoggedIn=1时,才应列出页面ID 2 仅当@IsLoggedIn=1和@IsAdmin=1时,才应列出页面ID 3 页面ID 4应该一直列在列表中,除非@IsLoggedIn=1。很可能有些页面需要登录用户甚至管理员用户,但仍然需要隐藏-这是我大脑爆炸的地方。。。 页面ID 5应始终可见,无论用户是否登录,也不管他们是否是管理员,因为它不需要登录,并且对于登录的用户它不会隐藏 对我有用

评论后编辑:

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 fiddle:

对于@IsLoggedIn=1,显示IsAdmin=0-PageID 2,5

SELECT  PageID ,
            RequireLogin ,
            RequireAdmin ,
            HideIfLoggedIn
    FROM    tbl_Page
    WHERE 
   (@IsLoggedIn = 1 AND [HideIfLoggedIn] = 0) 
   AND [RequireLogin] = @IsLoggedIn
   AND [RequireAdmin] = @IsAdmin         
对于@IsLoggedIn=1,显示IsAdmin=1-PageID 2,3,5

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

对于@IsLoggedIn=0,显示IsAdmin=1-PageID 4,5。

我认为当where子句围绕负数结构时,它的可读性更好

SELECT  PageID ,
            RequireLogin ,
            RequireAdmin ,
            HideIfLoggedIn
    FROM    tbl_Page
    WHERE 
   (@IsLoggedIn = 1 AND [HideIfLoggedIn] = 0) 
   AND [RequireLogin] = @IsLoggedIn
   AND [RequireAdmin] = @IsAdmin         
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)
    )

你能以表格形式提供样品记录吗?我个人更喜欢你提供的格式。使设置SQL FIDLE更容易。关于3,如果一个页面同时设置了RequireLogin和HideIfLoggedIn,这是否意味着不管@IsLoggedIn的值是多少,都应该将其排除在外?或者一个偏好优先于另一个吗?非常接近–做得很好,但是我错过了我的示例中最常见的一次,当RequireLogin=0和RequireReadMin=0和HideIfLoggedIn=0时,这表明任何人都应该看到一些东西-无论是否登录,我也需要调整您的答案以考虑到这一点我已经修改了我的问题,将这个场景页面ID 5包括在内——我想看看你是如何解决这个问题的:好的,更新了;由于这个新案例与其他逻辑并不匹配,特别是@IsLoggedIn,我认为最简单的方法是在末尾添加最后一个检查来捕获特定的组合。所有更新的示例现在都可以工作了;让我知道进展如何。