Mysql 嵌套视图按顺序忽略顺序

Mysql 嵌套视图按顺序忽略顺序,mysql,nested,subquery,views,greatest-n-per-group,Mysql,Nested,Subquery,Views,Greatest N Per Group,与此类似的问题: 我有以下显示的表格: 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`) ) ENGI

与此类似的问题:

我有以下
显示的
表格:

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
我想创建一个视图,该视图将为每个
show\u类型返回最高
show\u年份的
show\u id
。这里有一个嵌套查询,有效-返回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 |
+---------+------------------+
*/
第二个应根据第一个进行分组:

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`;
然而,令我惊讶的是,它返回了不正确的行。好像它分组忽略子视图的顺序:

+---------+-----------+
| show_id | show_year |
+---------+-----------+
|       3 |      2015 |
|       1 |      2014 | <== why?
+---------+-----------+
+---------+-----------+
|展会id展会年份|
+---------+-----------+
|       3 |      2015 |
|1 | 2014 |Lew me专注于此:

我想创建一个视图,该视图将返回最高值的show_id 每种演出类型的演出年份。下面是一个有效的嵌套查询- 返回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 |
+---------+-----------+
*/
这里有一种方法,假设
show\u id
递增,因此最大的
show\u 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的工作方式有“一厢情愿”的理解。您正在使用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);
编辑二:

如果每个
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
                        )
                 );
我想创建一个视图,该视图将返回最高值的show_id 每种演出类型的演出年份

(如中所示。)

通常,可以有许多具有给定演出类型的最大演出年份的演出ID。(正如他在评论中指出的那样。)

如果你只想返回其中一个,那么在你的问题中说出是哪一个。对于最大值:

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`;
或者,如果您想要每个节目类型的最大节目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`;
那么,在视图中,如何在GROUP BY之前应用ORDER BY

如果要对SELECT的结果进行排序,则必须在其GROUP BY之后按order BY进行排序。因此,若要在分组之前按订单,必须将外部选择与分组依据一起使用。如果选择的外部组位于视图中,则选择的内部订单可能必须位于第一个视图中命名的另一个视图中


但查询中命名的表或视图的顺序并不是通过计算其结果来保持的。那么,为什么您要在分组之前先按顺序订购?为什么您认为您的问题的嵌套视图应该返回每个显示类型的最大显示年份?

此查询用作我的视图。希望它能帮助任何人

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 |
+---------+-----------+-----------+
*/
其中为空-表示对于每个
show\u类型


整个模式和每个查询都显示在这里:

谢谢Gordon<代码>显示id
增量不可靠。但即使它是可靠的,如果我在那个表中有更多的列呢?每个都是马克斯?不起作用。第二个解决方案我不太明白,但它仍然返回2和4(而不是期望的2和3)。此外,不知何故,这两个结果似乎是以BLOB的形式显示的,十六进制看起来像32和34:-/Re:EDIT:我[出乎意料]能够基于这个嵌套查询创建一个视图,但是:a)它返回3个show_id:2、3和4,而不仅仅是2和3;b) 它无法返回其他年份(例如,如果您在原始shows表中添加了另一条记录,即show_type=3和show_year=2014)@Geo。它返回三个显示行,因为其中一个显示类型存在关联。因此,有三个符合您的标准。@Geo。是的,你的问题不清楚。此查询显示每个节目具有最长放映年份的行。只有一场演出时你想要什么?@Geo。您应该了解
分组方式的工作原理。它不会为值选择“第一”行。这里有详细的描述(),但重点是“不确定”一词。这与第一个值有很大的不同。这是您的两个观点:为什么您认为ORDER BY year的GROUP BY type只返回每种类型具有最大年份的行?为什么您认为查询中提到的表或视图的排序顺序不会被忽略?例如,我有3个节目:2012、2013和2014。DESC的第一批订单将使2014年的记录名列前茅。然后,GROUP BY将在2012年和2013年退出。至少我在嵌套查询的结果(但不是嵌套视图的结果)中看到了这一点。对“为什么”的回答太模糊,无法显示错误。该集团不会“摆脱”任何特定年份。Gordon Linoff的回答解释说,您的GROUP BY的SELECT不会返回任何特定的年份值;它不做你(大概)认为它做的事;这是错误的;这一次正好为这些数据给出了正确的答案。另外,在你的问题中,当一个类型有两个ID具有相同的高年份时,你希望得到什么结果。正确的是,它应该只具有两个ID,但不一定具有“相同的高年份”。事实上,根据这个特定的数据集,应该是两个不同的年份。换句话说,结果应具有与不同的
show\u type
值相同的记录数(因此按分组)。在我的例子中,每年每种类型都有两个节目。我想以2条记录结束,每条记录代表每个
show\u type
的最新节目。请让我知道这是否仍然不清楚,或者是否有不同的数据集
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 |
+---------+-----------+-----------+
*/