SQL连接表查找条件

时间:2014-09-04 07:19:05

标签: mysql sql where

我正在寻找两个表,标准是如果users表在分支代码字段中有任何内容,那么SQL查询将只返回它们的分支代码。

但是,如果users表在分支代码框中有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是登录的用户,则只返回他在Branch表中指定的BranchCode信息的查找:

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

2 个答案:

答案 0 :(得分:1)

也许有人更好的SQL会以纯SQL的方式来回答这个问题,但我倾向于保持我的查询相当简单,因为我喜欢在我的编码中遵循KISS规则。我希望他们这样做,因为这个答案并没有100%以你想要的方式回答你的问题。

使用您给我们的SQL,我可以假设您使用PHP进行此查询。此外,从您的查询中可以看出,您之前已经调用过users表。在THAT通话中,将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列,请随意忽略下一部分。

现在,我真的不确定为什么你的表的结构是这样的。我知道每个分支在交谈时可能都有一个字母数字的电话号码(例如,如果你打电话给另一个分支,你会说像#34;我是来自AW2011分支的杰克,......")但是{{3}是真实的,并且反击它的最好和最简单的方法之一是对引用变量进行类型转换,以便删除任何额外的输入。但是,这仅对整数类型的引用列有用,因为字符串列仍需要转义。考虑到这一点,您会注意到我在branchId周围使用mysqli_real_escape_string(),因为我知道它将是一个字符串值。

很多人会推荐像SQL Injection之类的东西,虽然我可能已经为你提供了链接,但它有时会让人很困惑,而且我并不完全是PHP的忠实粉丝#39; PDO连接。 MySQLi扩展还提供了自己的语句准备版本,这些都没有立刻让我感到惊讶。他们看起来都很复杂,我觉得不必要。但如果您需要使用字符串数据,它们绝对是避免SQL注入的最佳方法。

如果您的表格没有更多的参考,我无法确定您的数据实际上是什么样的,但我的逻辑是,如果您有一个user_id列,那么您将无法通过用户名栏。因此,我建议您在任何表上创建的每个记录都有一个ID列。这简化了对SQL注入的防护,因为我可以将mysql_real_escape_string()语句中的文本缩短为

而不是if()长度调用。
$sql .= 'WHERE branch_id='.(int)$_SESSION['branchId'];

在大多数情况下,这几乎应该是防范SQL注入所需的全部内容。如果有人要更改你的会话数据(我确信可能,但从未决定尝试),他们试图输入的任何额外文本都将被删除或导致SQL运行不正常。 (不过,请不要引用我的内容。我读过很久以前读过的关于PHP类型转换的变量,所以我可能完全错了。)

如果您不清楚ID列是什么或如何使用它,请随意提出另一个问题,希望有人比我向您解释的更准确。

答案 1 :(得分:1)

只是为了展示一种在纯SQL中执行此操作的方法。

你可以使用INNER JOIN做一个UNION,另一个使用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(我添加了UserName以更好地了解两个用户正在发生的事情,一个用NULL BranchCode,一个用有效的BranchCode)