2014-09-04 71 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)