2014-09-04 43 views
0

我正在尋找加入兩個表,條件是如果用戶表中有分支代碼字段中的任何內容,那麼SQL查詢將只返回其分支代碼。SQL加入表查找條件

但是,如果用戶表在分支代碼框中有NULL,它將返回分支表中的所有分支代碼。

下面是我正在嘗試,我知道不工作,但應該給我一些傾向的表和字段我正在使用。

SELECT IF(u.BranchCode IS NOT NULL THEN b.BranchCode ELSE u.BranchCode END) AS BranchCode, b.BranchName, b.BranchAddress1, b.BranchAddress2 
FROM users AS u 
LEFT JOIN branches AS b ON u.BranchCode = b.BranchCode 
WHERE u.Username = '$_SESSION[USERNAME]' 

一些表的例子:

用戶

UserName | BranchCode 
---------|------------------ 
bob  | NULL 
sam  | AW3456 
dave  | NULL 
alison | NULL 
fred  | NULL 

分行

BranchCode| BranchName |BranchAddress1 |BranchAddress2 
----------|-------------|---------------|------------------- 
AQ3459 | Northmore |1 Northmore Rd |Northmore Village 
AW3456 | Middleton |28 Main Rd  |Middleton Stoney 
DE5689 | Western  |451 Station Rd |Western 
FR3278 | Easterly |12 Acacia Dr |Easterly Estate 

因此,例如,如果Bob是用戶身份登錄,將返回所有的BranchCode信息的:

BranchCode| BranchName |BranchAddress1 |BranchAddress2 
----------|-------------|---------------|------------------- 
AQ3459 | Northmore |1 Northmore Rd |Northmore Village 
AW3456 | Middleton |28 Main Rd  |Middleton Stoney 
DE5689 | Western  |451 Station Rd |Western 
FR3278 | Easterly |12 Acacia Dr |Easterly Estate 

如果SAM是用戶身份登錄,因爲它在用戶表的規定,將返回他的BranchCode信息只查找:

BranchCode| BranchName |BranchAddress1 |BranchAddress2 
----------|-------------|---------------|------------------- 
AW3456 | Middleton |28 Main Rd  |Middleton Stoney 
+1

你的意思是說,你想要所有的數據從分支表中不與用戶錶鏈接? – 2014-09-04 07:27:11

+0

如果我說我不是你的SQL混淆的話,我會說謊。有什麼方法可以給我們一個快速的列表解釋和一些虛擬數據? – Jhecht 2014-09-04 07:32:28

+0

@Jhecht - 我重新閱讀後刪除了我的評論,這是'LEFT JOIN'/slaps_forehead – 2014-09-04 07:42:57

回答

1

也許有人誰與SQL更好的會來回答這個問題以純SQL方式,但我傾向於保持我的查詢非常簡單,因爲我喜歡在編碼中遵循KISS規則。我希望他們這樣做,因爲這個答案不會100%以您想要的方式回答您的問題。

隨着您給我們的SQL,我可以假設您使用PHP進行此查詢。此外,從您的查詢看來,您顯然已經預先調用了用戶表。在該呼叫中,將BranchId列存儲在會話中,就像您使用用戶名變量一樣。

隨着該$_SESSION['branchId']設置(儘管它可能是NULL)和你的mysqli_connect()調用存儲在一個名爲$con變量的假設,然後你可以做這樣的事情:

來回答這個問題(但不真的)

$sql = "SELECT * FROM branches"; 

if($_SESSION['branchId']!==null){ 
    $sql.= " WHERE BranchCode='".mysqli_real_escape_string($con,$_SESSION['branchId'])."'"; 
} 

$result = mysqli_query($con,$sql); 
//Fetch rows as usual. 

事項有關表結構

如果你已經有ID列的表,然後隨意忽略下一個部分。

現在,我真的不確定爲什麼你的表結構是這樣的。我知道每個分支在通話時可能會有一個字母數字的電話號碼(例如,如果你打電話給另一個分支,你會說「我是來自分支AW2011的傑克......」),但是SQL Injection是真實的,而且是最好的最簡單的方法來對付它是爲了強制引用變量,以便除去任何額外的輸入。但是,這對於引用整數類型的列是有用的,因爲字符串列仍然需要轉義。考慮到這一點,您會注意到我在branchId周圍使用了mysqli_real_escape_string(),因爲我知道這將是一個字符串值。

很多人都會推薦像Prepared Statements之類的東西,雖然我可能爲您提供了鏈接,但它有時可能會讓人感到困惑,而且我並不完全是PHP的PDO連接的忠實擁躉。 MySQLi擴展還提供了它自己的語句準備版本,這兩個版本都沒有讓我立即感到驚訝。他們都看起來很複雜,而且我感到毫無必要。但是,如果您需要使用字符串數據,它們絕對是避免SQL注入的最佳方式。

沒有更多關於你的表的參考,我不能確定你的數據實際是什麼樣的,但我的邏輯是,如果你有一個user_id列,你不會傳入username列。因此,我建議您在任何表上創建每個記錄都有一個ID列。這簡化守着因爲代替長度mysql_real_escape_string()通話不受SQL注入,我可以縮短在if()聲明文本

$sql .= 'WHERE branch_id='.(int)$_SESSION['branchId']; 

而且在大多數情況下,這應該是幾乎所有你需要警惕SQL注射。如果有人要改變你的會話數據(我敢肯定這是可能的,但從來沒有決定嘗試),他們試圖輸入的任何額外文本將被刪除或導致SQL運行不正確。 (不過,請不要在此引用我的內容,因爲我讀了很久以前我讀過的PHP類型轉換變量,所以我可能完全錯誤)。

如果您不清楚ID列是什麼或如何使用它,請隨時提出另一個問題,並希望有人比我能向您解釋更精確。

+0

非常感謝您的想法和潛在的解決方法,我將通過PHP實現這個方法,這是一個很好的解決方案。 – Palendrone 2014-09-04 09:16:26

1

只是爲了展示一種在純SQL中執行此操作的方法。

你可以做一個UNION,使用INNER JOIN,其他使用CROSS JOIN(因爲在這種情況下,兩個表之間沒有關係)

select b.BranchCode, b.BranchName, b.BranchAddress1, b.BranchAddress2 
from users u 
inner join branches b on u.BranchCode = b.BranchCode 
where u.UserName = '$_SESSION' 
and u.BranchCode is not null -- just for clarity, it's not neeeded 
union 
select b.BranchCode, b.BranchName, b.BranchAddress1, b.BranchAddress2 
from branches b 
CROSS JOIN users u 
where u.UserName = '$_SESSION[USERNAME]' 
and u.BranchCode is null 

看到SqlFiddle一個部分(我加的用戶名以更好地理解兩個用戶發生了什麼,一個用NULL BranchCode,一個用有效BranchCode)