MySQL挑战使用MIN和子查询

时间:2018-01-17 20:11:33

标签: mysql subquery

我的目的是根据所选年份返回日期值,并根据包含所有年份的完整数据集的数据集返回最小日期值。查询始终返回2017年的最小日期值。我希望它从整个数据集中返回最小的start_date。

我得到的是min_date_over_all_years

orgA    2017-10-09
orgB    2017-10-08

min_date_over_all_years的必需结果是

orgA        2015-10-10 
orgB        2014-10-09

请参阅附带的小提琴示例: http://sqlfiddle.com/#!9/c0f74/9

架构是:

CREATE TABLE IF NOT EXISTS `project` (
  `project_id` int(11) NOT NULL AUTO_INCREMENT,
  `p_name` varchar(10) NOT NULL,
  `start_date` DATE NOT NULL,
  `organisation_id` int(11) NOT NULL,
  PRIMARY KEY (`project_id`)
  ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

INSERT INTO `project` (`project_id`, `p_name`, 
`start_date`, `organisation_id`)
VALUES
(1, 'testP1', '2017-10-09', 1),
(2, 'testP2', '2016-10-10', 1),
(3, 'testP3', '2015-10-10', 1),
(4, 'testP4', '2017-10-10', 2),
(5, 'testP5', '2014-10-10', 2),
(6, 'testP6', '2017-10-10', 1),
(7, 'testP7', '2016-10-10', 1),
(8, 'testP8', '2015-10-10', 1),
(9, 'testP9', '2017-10-08', 2),
(10, 'testP10', '2014-10-09', 2);

CREATE TABLE IF NOT EXISTS `organisation` (`organisation_id` int(11) NOT NULL AUTO_INCREMENT,
`org_name` varchar(10) NOT NULL, 
 PRIMARY KEY (`organisation_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

INSERT INTO `organisation` (`organisation_id`, `org_name` 
)
 VALUES
(1, 'orgA'),
(2, 'orgB');

我试过的查询(以及更简单的子查询和Case版本)是:

SELECT o.org_name, MIN(p.start_date) AS min_date_2017, YEAR(p.start_date) AS year_selected,
(SELECT MIN(p.start_date) FROM project p2
INNER JOIN organisation o2 ON o2.organisation_id = p2.organisation_id
 WHERE p2.organisation_id = o.organisation_id
GROUP BY o2.organisation_id) AS min_date_over_all_years
FROM organisation o
INNER JOIN project p on p.organisation_id = o.organisation_id
WHERE YEAR(p.start_date)=2017
GROUP BY o.organisation_id

1 个答案:

答案 0 :(得分:0)

您不能放置在SELECT列表中返回多行的子查询;当子查询被用作表达式时,它必须返回一行包含单个列。

您不需要单独的查询。

SELECT o.org_name,
        MIN(IF(YEAR(p.start_date) = 2017, p.start_date, NULL)) AS min_date_2017,
        2017 AS year_selected,
        MIN(p.start_date) AS min_date_over_all_years
FROM organisation AS o
INNER JOIN project AS p ON p.organisation_id = o.organisation_id
GROUP BY o.organisation_id

您还可以使用获取整体数据的子查询加入。

SELECT o.org_name, MIN(p.start_date) AS min_date_2017, YEAR(p.start_date) AS year_selected, overall.start_date AS min_date_over_all_years
FROM organisation o
INNER JOIN project p on p.organisation_id = o.organisation_id
INNER JOIN (
    SELECT organisation_id, MIN(start_date) AS start_date
    FROM project 
    GROUP BY organisation_id) AS overall ON o.organisation_id = overall.organisation_id
WHERE YEAR(p.start_date)=2017
GROUP BY o.organisation_id