【问题标题】:Multiple joins in mysql tables with unionmysql表中的多个连接与联合
【发布时间】:2018-11-28 23:04:38
【问题描述】:

在 mysql 中,我在尝试获取正确数据时遇到问题。我想我必须使用 union 从两个表中获取所有结果,但不知道该怎么做。

表格说明:

  • 订单保留订单号
  • 员工持有员工
  • 区域包含区域名称
  • 实际时间有区域 ID、订单 ID 和交付所需的小时数
  • 交付详细信息包含员工 ID、员工交付的区域以及交付所需的小时数

订购

| id | number |
|----|--------|
| 1  |  0001  |

员工

| id | name |
|----|------|
| 1  | Jon  |

区域

| id | name  |
|----|-------|
| 1  | ZoneA |
| 2  | ZoneB |

实际时间

| id | zone_id | eta_hours | order_id |
|----|---------|-----------|----------|
| 1  |    1    |     5     |     1    |
| 2  |    2    |     4     |     1    |

deliver_details

| id | order_id | employee_id | zone_id | hours |
|----|----------|-------------|---------|-------|
| 1  |     1    |      1      |    1    |   3   |
| 2  |     1    |      1      |    1    |   1   |

我希望得到的是区域名称、交付所需的小时数以及员工交付的总小时数。如果员工没有交付到该区域,则显示 0

预期输出

| zone_name | hours | eta_hours | employee_name |
|-----------|-------|-----------|---------------|
|   ZoneA   |   4   |     5     |      Jon      |
|   ZoneB   |   0   |     4     |      Jon      |

我尝试在实际时间建立一个联合,但我没有做对。

这是我尝试过的(请注意,这只是为了获得正确的区域以及交付时间和实际时间)。

SELECT deliver_details.zone_id, actual_times.zone_id, zones.zone_name FROM actual_times
RIGHT JOIN deliver_details ON actual_times.order_id = deliver_details.order_id
INNER JOIN zones ON zones.id = deliver_details.zone_id
WHERE deliver_details.order_id = 1
GROUP BY deliver_details.zone_id
UNION ALL
SELECT deliver_details.zone_id, actual_times.zone_id, zones.zone_name FROM actual_times
LEFT JOIN deliver_details ON actual_times.order_id = deliver_details.order_id
INNER JOIN zones ON zones.id = actual_times.zone_id 
WHERE actual_times.order_id = 1
group by actual_times.zone_id

我非常想在一个查询中获得所有这些信息。有没有办法做到这一点?

请注意,这是对我遇到的更复杂问题的简化。如果您需要更多解释或有什么不明白的地方,请告诉我。

【问题讨论】:

    标签: mysql sql ruby-on-rails


    【解决方案1】:

    无需使用UNION

    从表employees 开始,然后与zonesactual_times 交叉连接以获得简单的笛卡尔积。然后在deliver_details 搜索每个员工在每个区域执行的交付;为此使用LEFT JOIN。如果 epmplyee 未在给定区域交付,请使用 COALESCE 返回 0 而不是 NULL

    查询:

    select
        z.name,
        coalesce(sum(dd.hours), 0),
        at.eta_hours,
        e.name
    from 
        employees e
        cross join zones z
        inner join actual_times at on at.zone_id = z.id
        left join deliver_details dd on dd.employee_id = e.id and dd.id = at.zone_id
    group by 
        z.name, at.eta_hours, e.name
    

    【讨论】:

    • 你在哪里定义了别名 z?我写了一个编辑版本并将问题回滚到你的版本检查我的版本..
    • @RaymondNijland:感谢您的评论!你完全正确,刚刚编辑了我的anwser(与你的修订几乎相同)
    • @GMB 感谢您的回答,不幸的是,查询无效。然而,它给了我一些想法,结合 Roppard 的回答让我找到了查询。
    【解决方案2】:

    我想出了一个与 GMB 类似的解决方案,但使用 UNION 来获取 0 小时的行...:

    SELECT z.name, sum(dd.hours), at.eta_hours, e.name 
    FROM zones z JOIN deliver_details dd ON z.id = dd.zone_id
    JOIN actual_times at ON z.id = at.zone_id
    JOIN employees e ON dd.employee_id = e.id
    GROUP BY z.name, at.eta_hours, e.name
    
    UNION
    
    SELECT z.name, 0, at.eta_hours, e.name
    FROM zones z JOIN actual_times at ON z.id = at.zone_id,
    employees e
    WHERE e.id NOT IN (SELECT employee_id FROM deliver_details WHERE zone_id = z.id)
    

    【讨论】:

    • 感谢您的回答。它帮助我找到了正确的查询。
    • 我很高兴它有帮助! (这实际上是我第一次在堆栈上回答问题。我自己问了一个问题,所以我需要回答其他人。宇宙现在很和谐!:D)
    【解决方案3】:

    如果每个区域只有一名员工,则以下查询应该适合您:

    SELECT   Z.name  AS zone_name
            ,DT.hours_total
            ,ACT.eta_hours_total
            ,E.name AS employee_name
    FROM zones Z
    INNER JOIN (SELECT  zone_id
                        , SUM(eta_hours) eta_hours_total 
                FROM actual_times 
                GROUP BY zone_id) ACT ON Z.zone_id = ACT.zone_id
    INNER JOIN (SELECT  zone_id
                        , employee_id
                        , SUM(hours) hours_total 
                FROM deliver_details 
                GROUP BY zone_id, employee_id) DT ON Z.zone_id = DT.zone_id
    INNER JOIN employees E ON DT.employee_id = E.employee_id
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-27
      • 2011-08-27
      相关资源
      最近更新 更多