【问题标题】:What kind of JOIN or WHERE clause do I need?我需要什么样的 JOIN 或 WHERE 子句?
【发布时间】:2013-11-25 13:25:55
【问题描述】:

我一直在尝试委托查询来获取 3 个表的列,但我不断得到不匹配的行。

这些是我的桌子:

消息
- 消息ID
- 发件人(可以是客户 ID 或员工 ID) - 接收者(可以是 customerID 或employeeID)

(注意:对于每条消息,它将仅包含 1 位客户和 1 位员工,即客户之间不互动,员工之间也不会互相发消息)

客户
- 客户 ID

员工
- 员工ID
- 部门ID

部门
- 部门ID
- 部门名称

对于 customerID = 5 的特定客户,我想弄清楚他们正在与之交谈的员工的 DepartmentName 是什么。

我最初的尝试是:

SELECT * FROM Messages,Employee, Departmnet, 
WHERE sender = '5' OR receiver = '5' 
AND (Employee.employeeID = Messages.sender OR Employee.employeeID = Messages.Receiver) 
AND Employee.departmentID = Department.DepartmentID;

但是,这会返回比预期更多的行。我认为这是因为发送者或接收者可能是员工 ID。

我的第二个猜测是也许我必须加入表格,但我在这方面没有太多经验。如果有人可以告诉我或告诉我如何执行此查询,我将不胜感激。

【问题讨论】:

  • 发布一些样本数据和想要的结果。
  • customerId 和employeeId 只是自动递增的ID,或者您确定客户和员工不能拥有相同的ID?
  • @rakeshjain 它们不是自动递增值,消息的创建方式确保客户只会向员工发送消息,而员工只会向客户发送消息。

标签: mysql sql join where-clause


【解决方案1】:

根本问题是您在此子句周围缺少括号:

sender = '5' OR receiver = '5' 

但是,我建议您使用 ANSI 样式的连接来使查询也更具可读性。

这应该会有所帮助:

SELECT * 
FROM Messages
INNER JOIN Employee ON (Employee.employeeID = Messages.sender OR Employee.employeeID = Messages.Receiver)
INNER JOIN Department ON Employee.departmentID = Department.DepartmentID
WHERE (Messages.sender = '5' OR Messages.receiver = '5');

【讨论】:

    【解决方案2】:

    你试过了吗:

    SELECT * FROM Messages m 
    INNER JOIN Employee e 
    INNER JOIN Departmnet d 
    ON ((m.sender=e.employeeId || m.receiver=e.employeeId) d.departmentId=e.departmentId) 
    WHERE m.sender = '5' OR m.receiver = '5'
    

    【讨论】:

    • 我已经测试了这个查询,这是一个解决方案。只需要在 where 子句周围加上括号。即 WHERE (m.sender = '5' OR m.receiver = '5')
    • @user3032422 如果它的工作,你能接受/投票的答案吗?
    • 我没有必要的 15 个声望点来这样做,但是一旦我得到它们,我保证会回到这里并这样做。
    【解决方案3】:

    您的问题实际上是您可以拥有一个与Customer 具有相同ID 的Employee,而无法区分两者。

    我认为更好的方法是将CustomersEmployees 视为Users,并将User 表链接到Role 表,告诉您他们是否是客户或雇员。

    另一种方法是创建一个 Message 表,其中包含一个 EmployeeID 字段和一个 CustomerID 字段,以及一个用于指定这是客户到员工还是员工到客户的字段。换句话说,一条已发送的消息,或一条已接收的消息。

    最后,如果您确定不会与客户 ID 和员工 ID 发生冲突,那么这很可能适用于您的查询:

    SELECT * 
    FROM Messages
    INNER JOIN Employee
    ON (
      (receiver = '5' AND Employee.employeeID = sender) OR
      (sender = '5'   AND Employee.employeeID = receiver)
    )
    INNER JOIN Department 
    ON Employee.departmentID = Department.departmentID;
    

    以上规定接收方和发送方不能同时是员工或客户。

    更新:澄清一下,一个字段不应该引用另外两个表,因为这样就不可能将其指定为外键。两个表的标识列可能存在冲突。例如,如果您有一个 ID 为 5 的客户和一个 ID 为 5 的员工,会发生什么?

    有一些技术可以处理这种情况,这里展示了一些技术:Foreign Key to multiple tables

    【讨论】:

    • 不鼓励使用 SQL 反模式,如隐式连接。让我们尝试将人们带入 21 世纪。
    • 重写。在我的辩护中,我想指出 OP 比隐式连接和显式连接有更大的问题。就像排除使用外键的数据库设计一样。
    • @GustavBertram 这是一个小打击.. 但是我在我的数据库架构上使用外键.. 而不是使用我的确切数据库架构,我淡化了我的示例以使其不那么混乱且更具可读性。
    • @user3032422 这并不是侮辱。我特别指的是Message 上的sender 可以同时指代EmployeeCustomer。这意味着您不能将其定义为外键,因为它不引用单个表。
    • 啊,是的,那是因为它使 Messages 表变得简单。如果我应用了外键,我需要创建一个字段来确定谁是发件人。这将需要比需要更多的逻辑。另外,消息不会很多。
    猜你喜欢
    • 2019-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多