订单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
让我焦虑不安!
答案 0 :(得分: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)