2010-01-17 65 views
1

拥有Mysql数据库,如果TUser.name不存在于变量@UserNames中,则必须选择所有(TUser.Name, TAccount.Name)对。
如果存在,我只能选择(TUser.Name, TAccount.Name)对,其中TUser.name@UserNamesMysql查询:如果列中存在值,则只选择该值,否则全选

喜欢的东西下面的查询的最后一行:

DECLARE @UserNames = "Alpha, Beta, Gama"; 

SELECT User.Name 
    , Account.Name 
    FROM TUser 
    , TAccount 
    , TUserAccount 
WHERE TAccount.ID = TUserAccount.AccountID 
    AND TUserAccount.UserID = User.ID 
-- please rewrite this line 
    AND TUser.Name IN (IFNULL ((SELECT ID FROM TUser WHERE Name IN @UserNames) , (SELECT ID FROM TUser))) 

预先感谢您!

回答

0
SELECT 
    User.Name, 
    Account.Name 
    FROM TUser 
     JOIN TAccount 
      ON TAccount.Name = TUser.Name 
     JOIN TUserAccount 
      ON TUserAccount.AccountID = TAccount.ID 
      AND TUserAccount.UserID = TUser.ID 
     LEFT JOIN (
      SELECT ID FROM TUser WHERE Name IN @UserNames 
     ) AS UsersFound 
      ON TUser.ID = UsersFound.ID 

这样的事情?我还没有测试过它。

+0

不返回只有匹配的名字在那种情况下 – 2010-01-17 22:00:46

+0

是的,我刚刚注意到,试图找出一个快速解决之前,我关闭了答案。 – William 2010-01-17 22:01:20

+0

IN @UserNames在这里不起作用。 @UserNames是“Alpha,Beta,Gama”,所以你的代码相当于说出名字在哪里(“Alpha,Beta,Gama”),但他想要在哪里(“Alpha”,“Beta”,“Gama” ) - 注意报价位置的差异。 – dcp 2010-01-17 22:01:26

1

你不能用你的标准返回相互排斥的结果集,而无需使用IF语句:

SELECT @sum := SUM(FIND_IN_SET(u.name, @UserNames)) 
    FROM TUSER u 

IF @sum > 0 THEN 

    SELECT u.name, 
      a.name 
     FROM TUSER u 
     JOIN TUSERACCOUNT ua ON ua.userid = u.id 
     JOIN TACCOUNT a ON a.id = ua.accountid 
    WHERE FIND_IN_SET(u.name, @UserNames) > 0 

ELSE 

    SELECT u.name, 
      a.name 
     FROM TUSER u 
     JOIN TUSERACCOUNT ua ON ua.userid = u.id 
     JOIN TACCOUNT a ON a.id = ua.accountid 

END IF; 

你可以做这项工作提供了PreparedStatement,MySQL的动态SQL,但你仍然需要运行查询以确定是否需要返回全部或子集。

参考文献:

0

好了,这就是我所说的 '黑客',而不是normall数据库查询,我会disrecommend得到的位置,你必须首先处理。正确的方法来处理的项目清单这样是为了让应用程序的语言解析它变成一个漂亮的列表,你可以用它来建立一个正常的,常规的SQL列表中,像这样:

TUser.Name IN ('Name1', 'Name2',...., 'NameX') 

但无论如何,如果你想坚持原来的问题,你的数据库是MySQL,你可以做一个远程理智的方式在这样一个查询:

SET @UserNames := 'Alpha,Beta,Gama'; 

SELECT  TUser.Name 
,   TAccount.Name 
FROM  TUser 
INNER JOIN TUserAccount 
ON   TUser.ID    = TUserAccount.UserID 
INNER JOIN TAccount 
ON   TUserAccount.AccountID = TAccount.ID 
WHERE  FIND_IN_SET(TUser.Name, @UserNames) 
OR  (SELECT COUNT(*) 
      FROM TUser.Name 
      WHERE FIND_IN_SET(TUser.Name, @UserNames)) = 0 

请注意,我也有所改变输入数据 - 这不是我在逗号后面没有空格。如果这是不可接受的,只需将查询中的每个出现@UserNames更改为REPLACE(@UserNames, ', ', ',')即可。同时请注意,它的性能下降,因为不可能使用TUser.Name上的任何索引来过滤特定用户。

我已经提到你真的应该做一个适当的IN你的数据列表。你可以在SQL如此直接做太多(动态SQL):

SET @UserNames := 'Alpha, Beta, Gama'; 

SET @stmt := CONCAT( 
' SELECT  TUser.Name' 
,' ,   TAccount.Name' 
,' FROM  TUser' 
,' INNER JOIN TUserAccount' 
,' ON   TUser.ID    = TUserAccount.UserID' 
,' INNER JOIN TAccount' 
,' ON   TUserAccount.AccountID = TAccount.ID' 
,' WHERE  TUser.Name IN (''', REPLACE(@UserNames, ', ', ''',''') , ''')' 
,' OR  (SELECT COUNT(*) ' 
,'   FROM TUser.Name' 
,'   WHERE TUser.Name IN (''', REPLACE(@UserNames, ', ', ''',''') , ''')) = 0' 
) 

PREPARE stmt FROM @stmt; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

(注意,在这种情况下,我可以使用的用户名列表与空间不变)

相关问题