我很熟悉从子组或表(for example)中查找最后一项,但我现在尝试使用嵌套连接对第二层执行相同的操作。
考虑以下架构和数据:
/*
SQLyog Ultimate v11.52 (64 bit)
MySQL - 5.6.17 : Database - test
*********************************************************************
*/
/*Table structure for table `companies` */
CREATE TABLE `companies` (
`company_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`company_name` varchar(16) DEFAULT NULL,
PRIMARY KEY (`company_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
/*Data for the table `companies` */
insert into `companies`(`company_id`,`company_name`) values (1,'Company1'),(2,'Company2');
/*Table structure for table `employees` */
CREATE TABLE `employees` (
`employee_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`company_id` int(10) unsigned NOT NULL,
`employee_name` varchar(16) NOT NULL,
PRIMARY KEY (`employee_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
/*Data for the table `employees` */
insert into `employees`(`employee_id`,`company_id`,`employee_name`) values (1,1,'Employee1'),(2,1,'Employee2'),(3,2,'Employee3'),(4,2,'Employee4');
/*Table structure for table `orders` */
CREATE TABLE `orders` (
`order_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`employee_id` int(10) unsigned NOT NULL,
`order_date` datetime NOT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;
/*Data for the table `orders` */
insert into `orders`(`order_id`,`employee_id`,`order_date`) values (1,1,'2016-02-01 00:00:00'),(2,1,'2016-02-02 00:00:00'),(3,2,'2016-02-03 00:00:00'),(4,2,'2016-01-28 00:00:00'),(5,3,'2016-01-29 00:00:00'),(6,3,'2016-01-30 00:00:00'),(7,4,'2016-01-31 00:00:00'),(8,4,'2016-01-27 00:00:00');
回答问题“每个员工的最后订单是什么?”是一个相对简单的问题:
SELECT c.company_name, e.employee_name, last_order.order_id, last_order.order_date
FROM employees e
JOIN companies c ON c.company_id = e.company_id
LEFT JOIN
(
SELECT o1.employee_id, o1.order_id, o1.order_date
FROM orders o1
LEFT JOIN orders o2 ON (o1.employee_id = o2.employee_id AND o1.order_date < o2.order_date)
WHERE o2.order_id IS NULL
) AS last_order ON last_order.employee_id = e.employee_id;
-- output ===================================================
company_name employee_name order_id order_date
Company1 Employee1 2 2016-02-02 00:00:00
Company1 Employee2 3 2016-02-03 00:00:00
Company2 Employee3 6 2016-01-30 00:00:00
Company2 Employee4 7 2016-01-31 00:00:00
但现在我需要问“每个公司的最后订单是什么?”,其中订单是另一层(companies > employees > orders
)。< / p>
我一直在试图弄清楚如何构建一个查询,允许我使用已经确定的“最后一个订单”将员工加入员工,以便进行相同的比较:
-- pseudo code...
SELECT *
FROM employees e1
LEFT JOIN employees e2 ON (e1.company_id = e2.company_id AND e1.last_order_date < e2.last_order_date)
WHERE e2.employee_id IS NULL;
类似的东西,但由于“最后订单日期”是第一个查询的构造,我如何才能在每个员工表上显示这样的结果?
我是否需要使用大量嵌套查询来完成此类操作?临时表是否会成为更好的解决方案?我有什么简单的遗失吗?
我想最终得出每个公司的最后订单:
-- desired output ============================================
company_name employee_name order_id order_date
Company1 Employee1 1 2016-02-01 00:00:00
Company2 Employee3 5 2016-01-29 00:00:00
修改
“&gt;”在第一个查询中应该是“&lt;” - 我已经修改了这个以及输出来显示预期的内容: last 命令而不是第一个。为此道歉;这将最终用于做到这两点,我忘了改变示例的逻辑。
答案 0 :(得分:1)
修改强>
如果您想查看提供看似正常但实际上错误的结果的旧答案,请检查编辑历史记录。
如果公司有多个订单且完全相同 order_date
,则以下查询将提取多行。 (下面有一个更强大的解决方案)
SELECT
o.order_date
, o.order_id
, e.employee_id
, c.company_name
, e.employee_name
FROM (
SELECT
MAX(o.order_date) AS order_date, e.company_id
FROM orders o
INNER JOIN employees e ON o.employee_id = e.employee_id
GROUP BY e.company_id
) maxOrderDate
INNER JOIN orders o ON maxOrderDate.order_date = o.order_date
INNER JOIN employees e ON o.employee_id = e.employee_id AND o.employee_id = e.employee_id AND maxOrderDate.company_id = e.company_id
INNER JOIN companies c ON e.company_id = c.company_id
以下查询解释了那些讨厌的多个订单与完全相同的订单状态
SELECT
o.order_date
, o.order_id
, e.employee_id
, c.company_name
, e.employee_name
FROM (
SELECT MAX(o.order_id) AS order_id
FROM (
SELECT
MAX(o.order_date) AS order_date, e.company_id
FROM orders o
INNER JOIN employees e ON o.employee_id = e.employee_id
GROUP BY e.company_id
) maxOrderDate
INNER JOIN orders o ON maxOrderDate.order_date = o.order_date
INNER JOIN employees e ON o.employee_id = e.employee_id AND o.employee_id = e.employee_id AND maxOrderDate.company_id = e.company_id
GROUP BY e.company_id
) maxOrder
INNER JOIN orders o ON maxOrder.order_id = o.order_id
INNER JOIN employees e ON o.employee_id = e.employee_id
INNER JOIN companies c ON e.company_id = c.company_id