【问题标题】:MySQL: Select one row from left join only once in result wth multiple rowsMySQL:从左连接中选择一行只在结果中有多行
【发布时间】:2014-06-22 01:42:15
【问题描述】:

好的,在 SO 的帮助和我自己公认的有限脑力的帮助下,我的查询大部分都在工作。我从LEFT JOIN 得到了我想要的结果,它显示在外部查询中。但是,对于具有相同 ID 的每一行,它会显示多次,这是意料之中的,但这不是我所需要的......

我想知道是否可以只显示一次连接结果。我在网上找到了很多答案,只从一个左连接的表中提取第一行。但是,我正在寻找的是只在结果中显示一次连接结果(不一定是第一次)。

这是我的查询的[简化版]:

select
    `order`.order_id,
    `order`.total,
    `order`.comment,
    `order`.shipping_cost,
    `ct`.amount as credit
from `order`
left join (
    select
        customer_id,
        sum(amount) as amount
    from `customer_transaction`
    where
        amount > 0
        and integrated = 0
    group by
        customer_id
) as ct
    on `ct`.`customer_id` = `order`.`customer_id`
where
    `order`.integrated = 0;

这样做的目的是获取尚未集成的订单信息,同时包括客户信用。不幸的是,信用作为行存储在ct 表中,与特定订单无关,这是有道理的,但集成它的软件希望订单上有这个数字。

上述查询“有效”,直到一位客户有多个订单。在这种情况下,如果我使用上述查询,它将有效地认为所有订单都已应用信用。例如,上面的查询返回如下结果:

+-------------+----------+-----------+---------+---------------+--------+
| customer_id | order_id | total     | comment | shipping_cost | credit |
+-------------+----------+-----------+---------+---------------+--------+
|       52227 |   184589 |   28.6910 |         |       12.7410 | 8.0000 |
|       52227 |   184590 |   28.6910 |         |       12.7410 | 8.0000 |
+-------------+----------+-----------+---------+---------------+--------+

这位客户的“帐户”上有 8 美元的信用额度,而不是 16 美元。即,客户未使用的信用交易总和为 8。我试图让该信用只出现一次。换句话说,这就是我想要的结果:

+-------------+----------+-----------+---------+---------------+--------+
| customer_id | order_id | total     | comment | shipping_cost | credit |
+-------------+----------+-----------+---------+---------------+--------+
|       52227 |   184589 |   28.6910 |         |       12.7410 | 8.0000 |
|       52227 |   184590 |   28.6910 |         |       12.7410 | NULL   |
+-------------+----------+-----------+---------+---------------+--------+

(注意右下角的 NULL。它也可能是 0,甚至可能是 8/$NUM_ROWS。我必须检查软件是否可以使用它。可能不会。)

这种疯狂的原因是因为一个软件将信用存储为与客户相关联的一行或多行,而另一个期望它作为一个订单的一部分,并且它应该“一次”全部集成。它运行一个查询以获取所有订单信息,包括信用,以及第二个用于订单项(无信用)。所以...我需要在订单中加入信用,然后将其设置为integrated=1,这样下次就不会使用它了(我已经有这部分工作了)。

任何想法我只能显示一次信用,或者这不是通过“简单”查询(而不是代码)来实现的吗?

谢谢

【问题讨论】:

  • 使用您的测试数据创建SQL Fiddle 并发布预期结果。

标签: mysql sql join left-join


【解决方案1】:

您可以通过使用左连接来做到这一点。这个想法是在left join的第一个表中有一个序列号:

select o.order_id, o.total, o.comment, o.shipping_cost, ct.amount as credit
from (select o.*,
             @rn :=  if(@cid = customer_id, @rn + 1, 1) as rn,
             @cid := customer_id
      from `order` o cross join
           (select @rn := 0, @cid := 0) vars
     ) o left join
     (select customer_id, sum(amount) as amount
      from `customer_transaction`
      where amount > 0 and integrated = 0
      group by customer_id
     ) ct
     on `ct`.`customer_id` = o.`customer_id` and o.rn = 1
where o.integrated = 0;

如有必要,left join 保留第一个表中的所有行和第二个表中的匹配行。因为条件o.rn = 1只匹配第一行,所以只有第一行会得到值。

【讨论】:

    猜你喜欢
    • 2013-10-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 2013-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多