2010-01-17 66 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; 

(注意,在這種情況下,我可以使用的用戶名列表與空間不變)

相關問題