MySQL:从左连接中仅选择一行,结果为多行

标签 mysql sql join left-join

好吧,在 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 这样下次就不会使用它(我已经让这部分工作了)。

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

谢谢

最佳答案

您可以使用左连接来做到这一点。这个想法是在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只匹配第一行,所以只有第一行会得到值。

关于MySQL:从左连接中仅选择一行,结果为多行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24347429/

相关文章:

sql - 合并结果或留给客户端浏览器 javascript 的高效 SQL?

mysql - SQL 查询查找拥有未发布应用程序的用户

sql - 无法绑定(bind)多部分标识符 - 子查询

mysql - 如何将数组插入到数据库中的字段 - wordpress

mysql - 标签时 Sublime Text 2 将 0 更改为日期

mysql - 从另一个表中计算行的更快方法

mysql - 缩短 sql 查询

python - python twitter Streamer 中的引号问题

mysql - CAST unsigned to signed int 在 MySql

python - 连接两个具有不同索引级别数的 MultiIndex DataFrame