我有这种模式:
Customer (1) .... (n) Orders
我可以通过简单的查询找到一个客户的所有订单:
select * from Orders o join Customer c on o.customer_id = c.id;
我需要找到所有客户的所有当前(今天)订单(如果他们有),展示所有客户。
EG。我期待的结果是这样的:
Customer OrderDate OrderStatus
Customer 1 2/1/2015 12:00:00 active
Customer 2 2/1/2015 13:00:00 closed
Customer 3 null null
Customer 4 null null
表格应如下所示:
Customers
Customer 1
Customer 2
Customer 3
Customer 4
Orders timestamp CustomerID
Active 1/1/2015 15:00:00 1
Closed 1/1/2015 08:00:00 1
Canceled 1/1/2015 09:00:00 1
Closed 2/1/2015 11:00:00 1
Active 2/1/2015 12:00:00 1 //This is the last one of "TODAY" C1
Active 3/1/2015 18:00:00 1
Closed 2/1/2015 13:00:00 2 //This is the last one of "TODAY" C2
正在运行的查询是:
select o.status, o.date, c.name from (
select c.*, (
select o1.id from orders o1
where o1.id_customer = c.id and o1.date between '2/1/2015 00:00:00' and "2/1/2015 23:59:59"
order by o1.date desc limit 1) as o
from cliente c
) c left join orders o on o.id = c.o;
问题是,对于少量订单和客户,查询需要几秒钟才能执行。我预计短期内订单数量也会增加,客户数量也会增加。
有没有办法提高这个查询的效率?我觉得我是以错误的方式解决问题。
旁注:我无法修改模型,不能包含新列。我的第一个解决方案是向客户提供最后一个订单,并在每次创建订单时设置它,但遗憾的是我无法更改数据库。
提前致意并表示感谢!
[编辑]
表定义
CREATE TABLE `customer` (
`id` char(36) NOT NULL,
`name` varchar(120) NOT NULL,
`cabin` enum('CABIN_A','CABIN_B','CABIN_C','CABIN_D','CABIN_E') DEFAULT NULL,
`addressId` char(36) NOT NULL,
`phone` varchar(45) DEFAULT NULL,
`datetime` timestamp NULL DEFAULT NULL,
`number` bigint(20) unsigned NOT NULL,
`unitId` char(36) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
UNIQUE KEY `number_UNIQUE` (`number`),
KEY `addressId_idx` (`addressId`),
KEY `fk_customer_unit_idx` (`unitId`),
CONSTRAINT `fk_customer_unit` FOREIGN KEY (`unitId`) REFERENCES `unidad` (`unitId`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_address_customer` FOREIGN KEY (`addressId`) REFERENCES `address` (`addressId`) ON DELETE CASCADE ON UPDATE NO ACTION,
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `orders` (
`id` char(36) NOT NULL,
`customerId` char(36) NOT NULL,
`status` enum('ACTIVE','CLOSED','CANCELED') NOT NULL,
`datetime` timestamp NULL DEFAULT NULL,
`comment` varchar(700) DEFAULT NULL,
`programDate` timestamp NULL DEFAULT NULL,
`cabin` varchar(10) DEFAULT NULL,
`unitId` char(36) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `fk_orders_unit_idx` (`unitId`),
CONSTRAINT `fk_customer_orders` FOREIGN KEY (`customerId`) REFERENCES `customer` (`customerId`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_unit` FOREIGN KEY (`unitId`) REFERENCES `unit` (`unitId`) ON DELETE NO ACTION ON UPDATE NO ACTION,
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
答案 0 :(得分:2)
没有子查询的简单LEFT JOIN
应该可以加快速度:
select o.status, o.date, c.name
from Orders o
join Customer c
on o.customer_id = c.id
AND o.orderDate = '2/1/2015'
我假设,根据原始问题(来自“我期待的结果......”),您希望任何今天没有订单的客户返回NULL。
我有点困惑为什么客户#1的2'已关闭'和1'已取消'订单不属于“我期待的结果”,因为您的“查询”中不需要orderStats = 'Active'
正在运作“......显然,既然你列出了客户#2的已关闭订单,实际上并不是要求订单开放 - 也许你想详细说明这一点。
答案 1 :(得分:0)
我会选择一个更简单的解决方案,使用LEFT JOIN:
SELECT c.name AS Customer,
o.date AS OrderDate,
o.status AS OrderStatus
FROM cliente c
LEFT JOIN orders o ON (o.id_customer = c.id AND o.date = '2/1/2015')
但我想知道为什么你想要选择这两者之间唯一的第一行:
Closed 2/1/2015 1
Active 2/1/2015 1
这个id是什么?顾客ID?订单ID?不是那么清楚......
答案 2 :(得分:0)
请查看此页面:http://www.mysqltutorial.org/mysql-row_number/
我认为您可以使用每个组的行号。您必须由客户打理,订单是customer_id,status。 在获得行号后,只需选择数字1。