English version (when available)
select datediff( (select max(fecha) from pedido), (select min(fecha) from pedido) ) dias;Solución alternativa:select datediff(max(fecha), min(fecha)) dias from pedido;
select (select count(*) from tv) tv, (select count(*) from camara) camaras, (select count(*) from objetivo) objetivos;
select (select count(*) from tv)/(select count(*) from articulo)*100 tvPC, (select count(*) from camara)/(select count(*) from articulo)*100 camarasPC, (select count(*) from objetivo)/(select count(*) from articulo)*100 objetivosPC;Solución alternativa:La solución alternativa es más eficiente, solo utiliza ARTICULO 1 vez. En la solución principal se recorre 3 veces para obtener el mismo dato cada vez.select (select count(*) from tv)/t.total*100 tvPC, (select count(*) from camara)/t.total*100 camarasPC, (select count(*) from objetivo)/t.total*100 objetivosPC from (select count(*) total from articulo) t;
select email,nombre, apellidos,numpedido, valor from usuario u left join (select p.numpedido,usuario, sum(cantidad*importe) valor from pedido p, linped l where p.numpedido=l.numpedido group by numpedido,usuario having sum(cantidad*importe)>10000) calculo on (email=usuario) where provincia='03' order by valor desc
select email,nombre,apellidos,numpedido,pendiente FROM usuario u JOIN (select numpedido,usuario from pedido where numpedido not in (select numpedido from linped)) pedidos ON email=pedidos.usuario -- pedidos sin líneas JOIN (select usuario,sum(pvp) pendiente from cesta c, articulo a where c.articulo=a.cod group by usuario) cestas ON email=cestas.usuario; -- valor de sus cestas
WITH contados AS (SELECT p.usuario, u.apellidos, u.nombre, MONTH(fecha) mes, COUNT(*) pedidos FROM pedido p JOIN usuario u ON p.usuario=u.email WHERE YEAR(fecha)=2010 GROUP BY usuario, u.apellidos, u.nombre, MONTH(fecha) ) SELECT usuario, apellidos, nombre, MAX(IF(mes = 1, pedidos, 0)) AS Ene, MAX(IF(mes = 2, pedidos, 0)) AS Feb, MAX(IF(mes = 3, pedidos, 0)) AS Mar, MAX(IF(mes = 4, pedidos, 0)) AS Abr, MAX(IF(mes = 5, pedidos, 0)) AS May, MAX(IF(mes = 6, pedidos, 0)) AS Jun, MAX(IF(mes = 7, pedidos, 0)) AS Jul, MAX(IF(mes = 8, pedidos, 0)) AS Ago, MAX(IF(mes = 9, pedidos, 0)) AS Sep, MAX(IF(mes = 10, pedidos, 0)) AS Oct, MAX(IF(mes = 11, pedidos, 0)) AS Nov, MAX(IF(mes = 12, pedidos, 0)) AS Dic FROM contados GROUP BY usuario, apellidos, nombre HAVING SUM(pedidos) > 1;Solución alternativa:La solución aprovecha que la CTE genera una fila por cada usuario y mes en el que tenga pedidos.select * from (select email,nombre,apellidos, (select count(*) from pedido where month(fecha)=1 and year(fecha)=2010 and usuario=email) enero, (select count(*) from pedido where month(fecha)=2 and year(fecha)=2010 and usuario=email) febrero, (select count(*) from pedido where month(fecha)=3 and year(fecha)=2010 and usuario=email) marzo, (select count(*) from pedido where month(fecha)=4 and year(fecha)=2010 and usuario=email) abril, (select count(*) from pedido where month(fecha)=5 and year(fecha)=2010 and usuario=email) mayo, (select count(*) from pedido where month(fecha)=6 and year(fecha)=2010 and usuario=email) junio, (select count(*) from pedido where month(fecha)=7 and year(fecha)=2010 and usuario=email) julio, (select count(*) from pedido where month(fecha)=8 and year(fecha)=2010 and usuario=email) agosto, (select count(*) from pedido where month(fecha)=9 and year(fecha)=2010 and usuario=email) septiembre, (select count(*) from pedido where month(fecha)=10 and year(fecha)=2010 and usuario=email) octubre, (select count(*) from pedido where month(fecha)=11 and year(fecha)=2010 and usuario=email) noviembre, (select count(*) from pedido where month(fecha)=12 and year(fecha)=2010 and usuario=email) diciembre from usuario) pormeses where enero+febrero+marzo+abril+mayo+junio+julio+agosto+septiembre+octubre+noviembre+diciembre > 1;
La solución alternativa, siendo más "entendible", es mucho más ineficiente que la proporcionada, "recorre" la tabla pedido 12 veces. En nuestra base de datos, pequeña, no es importante, pero no se aconseja recurrir a soluciones así.
select provincia,count(*) pedidos from usuario u, (select usuario,p.numpedido,sum(importe*cantidad) total from pedido p join linped l on (p.numpedido=l.numpedido) group by usuario,numpedido) pd where u.email=pd.usuario group by provincia having avg(total)>2500;Solución alternativa:El problema aquí reside en calcular el importe medio de los pedidos por cada provincia. Piensa que si planteas:WITH PD AS (select usuario,p.numpedido,sum(importe*cantidad) total from pedido p join linped l on (p.numpedido=l.numpedido) group by usuario,numpedido) select provincia,count(*) pedidos from usuario u,PD where u.email=PD.usuario group by provincia having avg(total)>2500;
select provincia,count(*),avg(importe*cantidad)
from usuario u,pedido p,linped l
where u.email=p.usuario and p.numpedido=l.numpedido
group by provincia
Lo que está calculando es el promedio de importe*cantidad de todas las líneas de pedidos en cada provincia.
Plantéalo como un problema por etapas. Primero, usuario (lo necesitaremos después), numpedido e importe total de los pedidos:
select usuario,p.numpedido,sum(importe*cantidad) totalpedido
from pedido p,linped l
where p.numpedido=l.numpedido
group by usuario,p.numpedido
Supongamos que llamamos a lo anterior PD. Ahora lo integramos en la consulta que realmente queremos hacer:
select provincia,count(*) pedidos
from usuario u, PD
where u.email=PD.usuario
group by provincia
having avg(totalpedido)>2500;
La solución alternativa, usando CTE, es la sintaxis más cercana a esta explicación.
select distinct l.pueblo from usuario u, localidad l where u.pueblo = l.codm and u.provincia=l.provincia and email in (select usuario from pedido p group by usuario having count(*)>=2);Solución alternativa:select distinct l.pueblo from usuario u, localidad l, pedido p where u.pueblo = l.codm and u.provincia=l.provincia AND u.email=p.usuario group by usuario,l.pueblo,u.provincia having count(*)>=2; -- ---- select l.pueblo from localidad l, (SELECT distinct u.pueblo,u.provincia from pedido p JOIN usuario u ON p.usuario=u.email group by p.usuario,u.pueblo,u.provincia having count(*)>=2) pp where pp.pueblo = l.codm and pp.provincia=l.provincia;
select tv.cod,panel,(select round(avg(pantalla),0) from tv where resolucion='1920 x 1080') pantalla, resolucion, hdreadyfullhd, tdt from tv, articulo a where tv.cod=a.cod and marca='SONY';Solución alternativa:select tv.cod,panel,t.pantalla, resolucion, hdreadyfullhd, tdt from tv, articulo a,(select round(avg(pantalla),0) pantalla from tv where resolucion='1920 x 1080') t where tv.cod=a.cod and marca='SONY';
SELECT tvs/(tvs+cams+objs) promtv, cams/(tvs+cams+objs) promcam, objs/(tvs+cams+objs) promtv, (tvs+cams+objs) total FROM (SELECT COUNT(*) tvs FROM tv) t, (SELECT COUNT(*) cams FROM camara) c, (SELECT COUNT(*) objs FROM objetivo) oSolución alternativa:WITH t AS (SELECT COUNT(*) tvs FROM tv), c AS (SELECT COUNT(*) cams FROM camara), o AS (SELECT COUNT(*) objs FROM objetivo) SELECT tvs/(tvs+cams+objs) promtv, cams/(tvs+cams+objs) promcam, objs/(tvs+cams+objs) promtv, (tvs+cams+objs) total FROM t, c, o;
select totalAlicante, deAgost, round(deAgost/totalALicante*100,2) '% agostenses sobre alicantinos' from (select count(*) totalAlicante from usuario where provincia='03') t1, (select count(*) deAgost from usuario where provincia='03' and pueblo='0020') t2;Fíjate que hacemos un producto cartesiano de las subconsultas t1 y t2, pero ambas obtienen una única fila y una única columna, por lo que no es costoso para el motor de base de datos.
WITH maximos AS ( SELECT numpedido,MAX(cantidad) cants FROM linped GROUP BY numpedido ) SELECT provincia, AVG(cants) FROM maximos m JOIN pedido p ON m.numpedido=p.numpedido JOIN usuario u ON p.usuario=u.email GROUP BY provincia
SELECT marca,round(AVG(pvp)/(SELECT MAX(pvp) FROM articulo)*100,2) prom FROM articulo GROUP BY marca ORDER BY prom desc;Solución alternativa:WITH maximo AS ( SELECT MAX(pvp) AS max_pvp FROM articulo ) SELECT a.marca, ROUND(AVG(a.pvp) / m.max_pvp * 100, 2) AS prom FROM articulo a CROSS JOIN maximo m GROUP BY a.marca, m.max_pvp ORDER BY prom DESC;
WITH mmax AS ( SELECT marca FROM articulo WHERE pvp = (SELECT MAX(pvp) FROM articulo) ) SELECT articulo, importe FROM linped l JOIN articulo a ON l.articulo=a.cod CROSS JOIN mmax WHERE a.marca = mmax.marca;Solución alternativa:SELECT articulo, importe FROM linped l JOIN articulo a ON l.articulo=a.cod WHERE a.marca = (SELECT marca FROM articulo WHERE pvp = (SELECT MAX(pvp) FROM articulo))
WITH media_marca AS ( SELECT marca, AVG(pvp) AS media_pvp FROM articulo GROUP BY marca ) SELECT a.cod, a.marca, a.pvp, l.importe FROM articulo a JOIN media_marca mm ON a.marca = mm.marca JOIN linped l ON l.articulo = a.cod WHERE a.pvp > mm.media_pvp;
WITH ventas_marca AS ( SELECT a.marca, SUM(l.cantidad) AS unidades FROM articulo a JOIN linped l ON l.articulo = a.cod GROUP BY a.marca ) SELECT marca, unidades FROM ventas_marca WHERE unidades = ( SELECT MAX(unidades) FROM ventas_marca );
WITH packtotal AS ( SELECT pack, SUM(pvp) AS coste FROM ptienea p JOIN articulo a ON p.articulo=a.cod GROUP BY pack ) SELECT a.cod,a.nombre,a.pvp,t.coste FROM pack k JOIN articulo a ON k.cod=a.cod JOIN packtotal t ON t.pack=a.cod