SQL: 根据参数选择 CASE 或 IF,使用两种不同的 SELECT 查询。

huangapple go评论52阅读模式
英文:

SQL: CASE or IF based on parameter with 2 different SELECTS

问题

以下是您要翻译的内容:

在搜索或弄清楚这个问题时遇到了麻烦,但我想这应该很容易。

我有一个员工表

    姓名           管理员
    -------------------------
    金姆           
    约翰           
    扎克           
    蒂姆           

我有一个@parameter值,它提供了运行报告的用户名

基本上,我只想根据参数(用户)是管理员还是不是管理员返回2个不同的结果

    IF @NAME IN (SELECT NAME FROM employee where ADMIN = '是') THEN
           SELECT NAME FROM employee                        -- 返回表中的所有用户名
    ELSE
           SELECT NAME FROM employee where NAME = @NAME     -- 只返回1个用户名
    END

有人能指点我如何正确返回这个吗?提前感谢!

希望这有助于您理解您的查询代码。如果您有其他问题,请随时提出。

英文:

Having trouble searching or figuring this out, but imagine it should be pretty easy.

I have an employee table

NAME          ADMIN
-------------------------
Jim           Y
John          Y
Zack          N
Tim           N

I have a @parameter value which provides me the name that is running the report

I basically just want to return 2 different results based on if the parameter (user) is an admin

IF @NAME IN (SELECT NAME FROM employee where ADMIN = 'Y') THEN
       SELECT NAME FROM employee                        -- return all names in table
ELSE
       SELECT NAME FROM employee where NAME = @NAME     -- just return the 1 username
END

Can someone point my in the right direction on how to return this properly? thanks in advance!

答案1

得分: 2

你应该抵制任何将这两种情况合并成单个 SELECT 语句的诱惑,因为每种情况的最佳执行计划不同(索引查找单行 vs. 全表扫描)。

你可能最好采取这样的方法,在非管理员情况下,只需命中满足 Name = @Name 的行一次(而不是首先查找是否为管理员,然后再获取实际值)。

如果他们不是管理员,你已经有了需要分配给标量变量的内容。如果他们是管理员,那么你可以继续进行完整的 select

DECLARE @Admin           CHAR(1),
        @SomeOtherColumn VARCHAR(50);
    
SELECT @Admin = Admin,
       @SomeOtherColumn = SomeOtherColumn
FROM   employee
WHERE  Name = @Name /*Needs to be unique key*/
    
IF @Admin = 'Y'
  SELECT Name,
         SomeOtherColumn
  FROM   employee
ELSE
  SELECT @Name AS Name,
         @SomeOtherColumn AS SomeOtherColumn
  WHERE @Admin IS NOT NULL /*If select to assign variables found no row return zero rows*/   
英文:

You should resist any temptation to combine the two cases into a single SELECT statement as the best execution plans for each won't be the same (index seek of a single row vs full scan).

You are probably best off doing something like this so in the non admin case you only need to hit the row where Name = @Name once (rather than first to find out they are not an admin and again to get the actual values).

If they are not an admin you already have what you need assigned to scalar variables. If they are an admin you then move onto the full select.

DECLARE @Admin           CHAR(1),
        @SomeOtherColumn VARCHAR(50);

SELECT @Admin = Admin,
       @SomeOtherColumn = SomeOtherColumn
FROM   employee
WHERE  Name = @Name /*Needs to be unique key*/

IF @Admin = 'Y'
  SELECT Name,
         SomeOtherColumn
  FROM   employee
ELSE
  SELECT @Name AS Name,
         @SomeOtherColumn AS SomeOtherColumn
  WHERE @Admin IS NOT NULL /*If select to assign variables found no row return zero rows*/   

答案2

得分: 1

以下是翻译好的部分:

这应该适用于您:

SELECT NAME FROM employee where ADMIN = 'Y'
IF(@@ROWCOUNT > 0)
SELECT NAME FROM employee -- 返回表中的所有姓名
ELSE
SELECT NAME FROM employee where NAME = @NAME -- 仅返回一个用户名

英文:

This should work for you:

SELECT NAME FROM employee where ADMIN = 'Y'
	IF(@@ROWCOUNT > 0) 
		SELECT NAME FROM employee                        -- return all names in table
	ELSE
		SELECT NAME FROM employee where NAME = @NAME     -- just return the 1 username

答案3

得分: 0

谢谢@MartinSmith指出这一点,我只需要在上面的代码中删除THEN和END:

IF @NAME IN (SELECT NAME FROM employee where ADMIN = 'Y') 
       SELECT NAME FROM employee                  -- 返回表中所有姓名
ELSE
       SELECT NAME FROM employee where NAME = @NAME  -- 只返回一个用户名

谢谢!

英文:

thanks you @MartinSmith for pointing this out, all I had to do was remove the THEN and END in my code above:

IF @NAME IN (SELECT NAME FROM employee where ADMIN = 'Y') 
       SELECT NAME FROM employee                  -- return all names in table
ELSE
       SELECT NAME FROM employee where NAME = @NAME  -- just return the 1 username

Thanks!

答案4

得分: 0

你有一个小的紧张点。

你想要一个"脆弱的代码",在其中有两个用于SELECT语句的路径,这些路径可能会不同步吗?

还是你想要保持脆弱性以最大化查询计划?

请参见下面的回答。如果你的表很小,我更喜欢"非脆弱的"代码。
请注意,下面的版本只有一个SELECT子句... 但是where子句有一个偏差。

创建表 #MyTableOne (Name VARCHAR(16), IsAdmin CHAR(1) NOT NULL)

将数据插入 #MyTableOne (Name, IsAdmin)


SELECT 'Jim','Y'
UNION ALL SELECT 'John','Y'
UNION ALL SELECT 'Zack','N'
UNION ALL SELECT 'Tim','N'

DECLARE @NameParameter VARCHAR(128)
/* 在这里尝试不同的值 */
SELECT @NameParameter = 'Jim'
SELECT @NameParameter = 'Tim'
SELECT @NameParameter = 'NotInTheTable'

DECLARE @MatchCount INT = 0

SELECT @MatchCount = COUNT(*) FROM #MyTableOne myAlias WHERE myAlias.Name = @NameParameter AND myAlias.IsAdmin = 'Y'

SELECT Name, IsAdmin FROM #MyTableOne myOuterAlias
WHERE
@MatchCount = 0 OR (myOuterAlias.Name = @NameParameter AND myOuterAlias.IsAdmin = 'Y')

删除表 #MyTableOne

当你的表/列很"小"的时候,我曾经看到过非常脆弱的代码... 就像下面这样

如果 @MagicValue = 1
BEGIN
从dbo.MyTable中选择A、B、C JOIN (一些连接排列方式 版本1) where ( 讨厌的where子句 #1 )
END

如果 @MagicValue = 2
BEGIN
从dbo.MyTable中选择A、B、C JOIN (一些连接排列方式 版本2) where ( 讨厌的where子句 #2 )
END

如果 @MagicValue = 3
BEGIN
从dbo.MyTable中选择A、B、C JOIN (一些连接排列方式 版本3) where ( 讨厌的where子句 #3 )
END

它可能会迅速失控... 在我看来。

英文:

You have a little tension point.

Do you want "fragile code" where you have 2 paths for SELECT statements that can get out of sync?

Or do you want to keep fragility to maximize the query plan?

See my answer below. If your table is small, I prefer "non fragile" code.
Note, the version below has only ONE SELECT clause... but with a deviation on the where clause.

CREATE TABLE #MyTableOne (Name VARCHAR(16), IsAdmin CHAR(1) NOT NULL) 


INSERT INTO #MyTableOne (Name, IsAdmin)

-------------------------
SELECT 'Jim', 'Y'
UNION ALL SELECT 'John', 'Y'
UNION ALL SELECT  'Zack', 'N'
UNION ALL SELECT  'Tim', 'N'


DECLARE @NameParameter VARCHAR(128) 
/* experiment here with the different values */
SELECT @NameParameter = 'Jim'
SELECT @NameParameter = 'Tim'
SELECT @NameParameter = 'NotInTheTable'


DECLARE @MatchCount INT = 0

SELECT @MatchCount = COUNT(*) FROM #MyTableOne myAlias WHERE myAlias.Name = @NameParameter AND myAlias.IsAdmin = 'Y'


SELECT Name, IsAdmin FROM #MyTableOne myOuterAlias
WHERE
@MatchCount = 0 OR (myOuterAlias.Name = @NameParameter AND  myOuterAlias.IsAdmin = 'Y')


DROP TABLE #MyTableOne

While your table/columns is "small", i have seen horribly fragile code....like the below

IF @MagicValue = 1
BEGIN
     SELECT A, B, C from dbo.MyTable JOIN (some permutation of joins here version 1) where ( nasty where clause #1  )
END

IF @MagicValue = 2
BEGIN
     SELECT A, B, C from dbo.MyTable JOIN (some permutation of joins here version 2) where ( nasty where clause #2  )
END

IF @MagicValue = 3
BEGIN
     SELECT A, B, C from dbo.MyTable JOIN (some permutation of joins here version 3) where ( nasty where clause #3  )
END

It can get so out of control....quickly, IMHO.

huangapple
  • 本文由 发表于 2023年6月15日 01:47:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76476287.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定