Mysql查询:如果列中存在值,则只选择值,否则选择全部

时间:2010-01-17 21:32:18

标签: sql mysql

拥有Mysql数据库,如果变量( TUser.Name, TAccount.Name )中不存在TUser.name,我必须选择所有@UserNames对。
如果存在,我必须仅选择( TUser.Name, TAccount.Name )TUser.name @UserNamesDECLARE @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 ) ) )

类似于以下查询的最后一行:

{{1}}

提前谢谢!

3 个答案:

答案 0 :(得分: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,但您仍然需要运行查询以了解是否需要返回全部或子集。

参考文献:

答案 1 :(得分: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

那样的东西?我没有测试过它。

答案 2 :(得分:0)

好的,所以这就是我称之为'hacks'而不是normall数据库查询,我不赞成首先处理你必须处理的位置。处理这类项目列表的正确方法是让您的应用程序语言将其解析为一个很好的列表,您可以使用它来构建一个普通的常规SQL IN列表,如下所示:

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;

(请注意,在这种情况下,我可以使用未更改空格的用户名列表)