w3school update descendente desc mysql nested subquery views greatest-n-per-group

update - order by mysql w3school



La vista anidada ignora ORDER BY (3)

Pregunta similar a esta: MySQL: Ver con subconsulta en la limitación de la cláusula FROM

Tengo la siguiente tabla de 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

Quiero crear una VISTA que devuelva show_id para el show_year más show_year para cada show_type . Aquí hay una consulta anidada que funciona : devuelve 2 y 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 | +---------+-----------+ */

Solo para la referencia también intenté la siguiente consulta que me pareció natural al principio, pero terminó siendo mala en mi caso, como se muestra a continuación:

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 | +---------+------------------+ */

Ahora, al crear una VISTA, basada en la consulta anidada anterior (la primera SELECCIÓN), el problema es que una vista no aceptará una subconsulta .

Entonces, estoy usando dos vistas. Uno dentro de otro.

El primero simplemente ordena la tabla por 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;

El segundo se supone que debe hacer el GRUPO BY en el primero:

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`;

Sin embargo, para mi sorpresa, devuelve filas incorrectas. Como si AGRUPARA ignorando el PEDIDO de la subvista:

+---------+-----------+ | show_id | show_year | +---------+-----------+ | 3 | 2015 | | 1 | 2014 | <== why? +---------+-----------+

Pistas?

PD: violín de SQL para empujar: http://sqlfiddle.com/#!2/e506d4/5


Quiero crear una VISTA que devuelva show_id para el show_year más alto para cada show_type.

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)

(Como en la respuesta de Gordon Linoff .)

En general, puede haber muchos show_ids con el máximo show_year de un show_type determinado. (Como también señaló en un comentario).

Si desea devolver solo uno de esos, dígalo y diga cuál en su pregunta. Para el máximo:

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);

Usar vistas anidadas para los ID con el año máximo por tipo:

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`;

O si desea el máximo show_id por show_type y maximum show_year:

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`;

Entonces, ¿cómo se puede aplicar ORDER BY antes de GROUP BY en una VISTA?

Si desea ordenar el resultado de un SELECT, debe hacerlo en su orden BY después de GROUP BY. Entonces, para ORDER BY antes de agrupar, debe usar un SELECT externo con un GROUP BY. Si el externo GROUP BY SELECT está en una vista, entonces el innner ORDER BY SELECT puede tener que estar en otra vista nombrada en la primera.

Pero el orden de una tabla o vista nombrada en una consulta no se mantiene calculando su resultado. Entonces, ¿por qué quieres ORDENAR antes de GROUP BY? ¿Por qué crees que las vistas anidadas de tu pregunta deberían mostrar un máximo de show_year por show_type?


Esta consulta funcionó como una VISTA para mí. Espero que ayude a cualquiera.

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 IS NULL: significa que no hay ningún registro que show_year HIGHER más que este para cada show_type

El esquema completo y cada consulta se muestran aquí: http://sqlfiddle.com/#!2/f28510/3


Lew, concéntrate en esto:

Quiero crear una VISTA que devuelva show_id para el show_year más alto para cada show_type. Aquí hay una consulta anidada que funciona: devuelve 2 y 3:

Aquí hay una forma, suponiendo que el show_id incremente, de modo que el show_id más show_id encuentre en el último año:

select show_type, max(show_year) as show_year, max(show_id) from shows group by show_type;

Si no, intente esto:

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;

La razón por la que tus otras consultas no funcionan es porque tienes una comprensión "deseosa" de cómo funciona MySQL. Está utilizando una extensión para MySQL que explícitamente dice que no funciona en la documentación . Es decir, las columnas en la select no están en funciones de agregación y no están en la cláusula group by (y no son funcionalmente dependientes, pero ese es un concepto muy avanzado que no es relevante para esta discusión):

En este caso, el servidor puede elegir libremente cualquier valor de cada grupo, de modo que, a menos que sean iguales, los valores elegidos son indeterminados, lo que probablemente no sea lo que usted desea.

EDITAR:

Lo siguiente también debería funcionar para una vista:

select s.* from shows s where s.show_year = (select max(s2.show_year) from shows s2 where s2.show_type = s.show_type);

EDIT II:

Si solo quieres una fila para cada show_type y show_id es única, entonces debería funcionar:

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 ) );