与此类似的问题: MySQL: View with Subquery in the FROM Clause Limitation
我有以下shows
表:
DROP TABLE IF EXISTS `shows`;
CREATE TABLE `shows` (
`show_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`show_type` int(11) unsigned DEFAULT NULL,
`show_year` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`show_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `shows` VALUES
(NULL, 1, 2014), -- 1
(NULL, 1, 2015), -- 2
(NULL, 2, 2015), -- 3
(NULL, 2, 2014); -- 4
我想创建一个VIEW,为每个show_id
的最高 show_year
返回show_type
。这是工作的嵌套查询 - 返回2和3:
SELECT s.show_id, s.show_year
FROM ( -- subquery for applying ORDER BY before GROUP BY
SELECT *
FROM shows
ORDER BY show_year DESC
) s
GROUP BY show_type;
/*
+---------+-----------+
| show_id | show_year |
+---------+-----------+
| 2 | 2015 |
| 3 | 2015 |
+---------+-----------+
*/
仅供参考我还尝试了以下对我来说很自然的查询,但最终在我的情况下没有好,如下所示:
SELECT s.show_id, MAX(s.show_year)
FROM shows s
GROUP BY show_type;
/*
+---------+------------------+
| show_id | MAX(s.show_year) |
+---------+------------------+
| 1 | 2015 | <== show_id=1 does NOT have show_year=2015
| 3 | 2015 |
+---------+------------------+
*/
现在创建一个VIEW - 基于上面的嵌套查询(第一个SELECT),问题是a view will not accept a subquery。
所以我使用了两个视图。一个在另一个里面。
第一个只是通过show_year DESC对表进行排序:
CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW `shows_desc` AS
SELECT `s1`.`show_id` AS `show_id`,
`s1`.`show_type` AS `show_type`,
`s1`.`show_year` AS `show_year`
FROM `shows` `s1`
ORDER BY `s1`.`show_year` DESC;
第二个应该在第一个上进行GROUP BY:
CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW `shows_grouped` AS
SELECT `s2`.`show_id` AS `show_id`,
`s2`.`show_year` AS `show_year`
FROM `shows_desc` `s2`
GROUP BY `s2`.`show_type`;
然而,令我惊讶的是它会返回错误的行。好像它已经忽略子视图的ORDER:
+---------+-----------+
| show_id | show_year |
+---------+-----------+
| 3 | 2015 |
| 1 | 2014 | <== why?
+---------+-----------+
线索?
P.S。:SQL小提琴:http://sqlfiddle.com/#!2/e506d4/5
答案 0 :(得分:4)
让我专注于此:
我想创建一个VIEW,它将返回最高的show_id 每个show_type的show_year。这是一个有效的嵌套查询 - 返回2和3:
这是一种方法,假设show_id
增量所以最近的show_id
是最近一年:
select show_type, max(show_year) as show_year, max(show_id)
from shows
group by show_type;
如果没有,试试这个:
select show_type, max(show_year) as show_year,
substring_index(group_concat(show_id order by show_year desc), ',', 1) as show_id
from shows
group by show_type;
您的其他查询不起作用的原因是因为您对MySQL的工作方式有“如意”的理解。您正在使用显式表示不在documentation中工作的MySQL扩展。也就是说,select
中的列不在聚合函数中,并且不在group by
子句中(并且不依赖于函数,但这是一个非常先进的概念,与此讨论无关):
在这种情况下,服务器可以自由选择每个组中的任何值, 所以,除非它们相同,否则所选择的值是不确定的, 这可能不是你想要的。
编辑:
以下内容也适用于视图:
select s.*
from shows s
where s.show_year = (select max(s2.show_year) from shows s2 where s2.show_type = s.show_type);
编辑II:
如果每个show_type
只需要一行,而show_id
是唯一的,那么这应该有效:
select s.*
from shows
where not exists (select 1
from shows s2
where s2.show_type = s.show_type and
(s2.show_year > s.show_year or
s2.show_year = s.show_year and s2.show_id > s.show_id
)
);
答案 1 :(得分:1)
此查询对我来说是一个VIEW。希望它可以帮助任何人。
SELECT s3.*
FROM shows s3
WHERE s3.show_id IN (
SELECT s1.show_id
FROM shows s1
LEFT JOIN shows s2
ON s1.show_type = s2.show_type
AND s2.show_year > s1.show_year
WHERE s2.show_id IS NULL
GROUP BY s1.show_type
);
/*
+---------+-----------+-----------+
| show_id | show_type | show_year |
+---------+-----------+-----------+
| 2 | 1 | 2015 |
| 3 | 2 | 2015 |
+---------+-----------+-----------+
*/
WHERE为空 - 表示对于每个show_year
show_type
比这更高的记录
整个架构和每个查询都显示在此处:http://sqlfiddle.com/#!2/f28510/3
答案 2 :(得分:0)
我想创建一个VIEW,它将返回最高的show_id 每个show_type的show_year。
select s.show_id
from shows s
where s.show_year=
(select max(st.show_year)
from shows st
where st.show_type=s.show_type)
(如Gordon Linoff's answer所示。)
通常,可以有许多show_ids,其中show_type的最大show_year。 (正如他在评论中也指出的那样。)
如果你想只返回其中一个,请说出你的问题中的哪一个。最大的一个:
select s.show_id
from shows s
where s.show_year=
(select max(st.show_year)
from shows st
where st.show_type=s.show_type)
and s.show_id=
(select max(st.show_id)
from shows st
where st.show_type=s.show_type
and st.show_year=s.show_year);
对每个类型最多年份的ID使用嵌套视图:
CREATE VIEW `shows_1` AS
SELECT `show_type` AS `show_type`,
MAX(`show_year`) AS `show_year`
FROM `shows`
GROUP BY `show_type`;
CREATE VIEW `shows_ids` AS
SELECT `s`.`show_id`
FROM `shows` `s`
JOIN `shows_1` `s1`
ON `s`.`show_type`=`s1`.`show_type`
AND `s`.`show_year`=`s1`.`show_year`;
或者,如果您想要每个show_type和最大show_year的最大show_id:
CREATE VIEW `shows_id` AS
SELECT MAX(`s`.`show_id`) AS `show_id`
FROM `shows` `s`
JOIN `shows_1` `s1`
ON `s`.`show_type`=`s1`.`show_type`
AND `s`.`show_year`=`s1`.`show_year`
GROUP BY `s`.`show_type`,`s`.`show_year`;
那么如何在VIEW中的GROUP BY之前应用ORDER BY?
如果要对SELECT的结果进行排序,则必须在其GROUP BY之后的ORDER BY中执行此操作。因此,对于GROUP BY之前的ORDER BY,必须使用带有GROUP BY的外部SELECT。如果外部GROUP BY SELECT在视图中,则内在的ORDER BY SELECT可能必须位于第一个中命名的另一个视图中。
但是查询中命名的表或视图的顺序不会通过计算结果来保留。那么为什么你想在GROUP BY之前订购BY?为什么您认为您的问题的嵌套视图应该为每个show_type返回最大show_year?