0

订单 has_many 交付

订单有一列 number_of_deliveries_paid_for

如何选择交货数量(COUNT(deliveries.id))小于number_of_deliveries_paid_for的所有订单

目前,我正在做:

Order.joins('LEFT OUTER JOIN deliveries ON deliveries.order_id = orders.id')
     .select('orders.*, COUNT(deliveries.id) AS delivery_count')
     .select { |o| o if o.number_of_deliveries_paid_for > o.delivery_count }

但这会返回一个数组,最好返回一个 ActiveRecord::Relation,我想在 sql 中执行它会更有效。

更新_ __ _ __ _ __ _ __ _ __

这似乎有效

Order.joins('LEFT OUTER JOIN deliveries ON deliveries.order_id = orders.id')
     .group('orders.id')
     .having('COUNT(deliveries.id) < orders.number_of_deliveries_paid_for')

我可以在它的末尾链接其他范围等。但是如果我添加.count到末尾,我会收到错误

ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column
'orders.number_of_deliveries_paid_for' in 'having clause':
SELECT COUNT(*) AS count_all, orders.id AS orders_id FROM `orders`
LEFT OUTER JOIN deliveries ON deliveries.order_id = orders.id GROUP BY orders.id 
HAVING COUNT(deliveries.id) < orders.number_of_deliveries_paid_for

这让我很焦虑!

4

1 回答 1

1

我不知道如何用 Ruby 编写它,但从 SQL 的角度来看,我觉得您需要一个子查询来按订单聚合交付数量。

类似的东西(我直接输入 SO - 请原谅拼写错误或愚蠢的语法错误):

SELECT orders.* FROM orders 
                LEFT OUTER JOIN (SELECT COUNT(*) AS C, deliveries.order_id AS ID
                                        FROM deliveries 
                                        GROUP BY deliveries.order_id) AS S
                ON orders.id = S.ID
                WHERE S.C < orders.number_of_deliveries_paid_for
                   OR (deliveries.id IS NULL AND orders.number_of_deliveries_paid_for > 0);

编辑:事实上,这使用起来要简单得多ORDER BY ... HAVING

SELECT *, count(*) AS C FROM orders 
                        LEFT OUTER JOIN deliveries 
                        ON deliveries.order_id = orders.id
       GROUP BY orders.id 
       HAVING C < orders.number_of_deliveries_paid_for
           OR (deliveries.id IS NULL AND orders.number_of_deliveries_paid_for > 0);

对于好奇的人,这是我的测试用例:

mysql> select * from orders;
+------+---------+-------------------------------+
| id   | name    | number_of_deliveries_paid_for |
+------+---------+-------------------------------+
|    1 | Order 1 |                             0 |
|    2 | Order 2 |                             2 |
|    3 | Order 3 |                             3 |
+------+---------+-------------------------------+
3 rows in set (0.00 sec)

mysql> select * from deliveries;
+----+----------+
| id | order_id |
+----+----------+
|  1 |        2 |
|  2 |        2 |
|  3 |        3 |
|  4 |        3 |
+----+----------+
4 rows in set (0.00 sec)

mysql> select * from orders JOIN deliveries ON deliveries.order_id = orders.id    -> ;
+------+---------+-------------------------------+----+----------+
| id   | name    | number_of_deliveries_paid_for | id | order_id |
+------+---------+-------------------------------+----+----------+
|    2 | Order 2 |                             2 |  1 |        2 |
|    2 | Order 2 |                             2 |  2 |        2 |
|    3 | Order 3 |                             3 |  3 |        3 |
|    3 | Order 3 |                             3 |  4 |        3 |
+------+---------+-------------------------------+----+----------+
4 rows in set (0.00 sec)

作为旁注,请参阅 和 之间的JOIN区别LEFT JOIN

mysql> select *, COUNT(*) from orders LEFT JOIN deliveries ON deliveries.order_id = orders.id group by orders.id;
+------+---------+-------------------------------+------+----------+----------+
| id   | name    | number_of_deliveries_paid_for | id   | order_id | COUNT(*) |
+------+---------+-------------------------------+------+----------+----------+
|    1 | Order 1 |                             0 | NULL |     NULL |        1 |
|    2 | Order 2 |                             2 |    1 |        2 |        2 |
|    3 | Order 3 |                             3 |    3 |        3 |        2 |
+------+---------+-------------------------------+------+----------+----------+
3 rows in set (0.00 sec)

mysql> select *, COUNT(*) from orders JOIN deliveries ON deliveries.order_id = orders.id group by orders.id;
+------+---------+-------------------------------+----+----------+----------+
| id   | name    | number_of_deliveries_paid_for | id | order_id | COUNT(*) |
+------+---------+-------------------------------+----+----------+----------+
|    2 | Order 2 |                             2 |  1 |        2 |        2 |
|    3 | Order 3 |                             3 |  3 |        3 |        2 |
+------+---------+-------------------------------+----+----------+----------+
2 rows in set (0.01 sec)
于 2013-07-09T12:52:16.630 回答