Subquery error in mysql - mysql

SELECT
c.cy_id AS cy_id,
(SELECT
c.to_id
FROM c
WHERE (c.to_id = se.ar))AS tsn,
(SELECT
se.x
FROM se
WHERE (c.to_id = se.ar)) AS X,
(SELECT
se.y
FROM se
WHERE (c.to_id = se.ar)) AS y
FROM (c
JOIN se)
WHERE (c.to_id = se.ar)
This above query when i execute in mysql gives error subquery returns more than one row.
But when i do the below query it returns the result.
SELECT
c.cy_id AS cy_id,
(SELECT DISTINCT
c.to_id
FROM c
WHERE (c.to_id = se.ar))AS tsn,
(SELECT
se.x
FROM se
WHERE (c.to_id = se.ar)) AS X,
(SELECT
se.y
FROM se
WHERE (c.to_id = se.ar)) AS y
FROM (c
JOIN se)
WHERE (c.to_id = se.ar).
I need an reason for this.

It appears your c table has multiple rows, but they all have the same to_id value. If multiple records are returned by a subquery, you'll get an error.
Also, your query doesn't appear to require any subqueries. Try this and see if it gets you the results you want:
SELECT
c.cy_id,
c.to_id AS tsn,
se.x AS X,
se.y AS y
FROM c
JOIN se
ON c.to_id = se.ar

Related

MySQL SUM(column) + (SUBQUERY WITH SUM)

I want to make a query that adds up points for a team. The points are added up by doing SUM on a column + a SUM from another table with the same team-id. I try to write it like this:
SELECT
k.id,
s.fylke,
s.Kommune,
s.Skolenavn,
k.schoolid,
k.number,
k.letter,
SUM(e.amount) + (SELECT SUM(poeng) FROM oppdrag WHERE klasseid=k.id ) AS poeng
FROM skoler AS s, klasser AS k, etappe AS e
WHERE s.id=k.schoolid AND k.id=e.klasseid AND e.year='2016'
GROUP BY k.id
ORDER BY poeng
The problem is that, when I write it in this fashion, it gives correct amount of points if the team has an entry in table "oppdrag" otherways it just returns NULL as points (poeng).
If your subquery returns NULL, this will result in trying to sum a number with NULL, which gives NULL back.
To fix this, you can try using the IFNULL function, that will replace it with a 0 if the query doesn't return any values:
SELECT
k.id,
s.fylke,
s.Kommune,
s.Skolenavn,
k.schoolid,
k.number,
k.letter,
SUM(e.amount) + IFNULL((SELECT SUM(poeng) FROM oppdrag WHERE klasseid=k.id ), 0) AS poeng
FROM skoler AS s, klasser AS k, etappe AS e
WHERE s.id=k.schoolid AND k.id=e.klasseid AND e.year='2016'
GROUP BY k.id
ORDER BY poeng
I'd avoid that subquery from your select statement, it's going to kill your performance. Also, you should really be using the correct join syntax (the style you're using is ancient). Try something like this;
SELECT
k.id,
s.fylke,
s.Kommune,
s.Skolenavn,
k.schoolid,
k.number,
k.letter,
SUM(e.amount) + ISNULL(SUM(od.poeng),0) AS poeng
FROM skoler AS s
INNER JOIN klasser AS k
ON s.id = k.schoolid
INNER JOIN etappe AS e
ON k.id = e.klasseid
LEFT JOIN oppdrag od
ON od.klasseid = k.id
WHERE e.year='2016'
GROUP BY k.id
ORDER BY poeng
First, learn to use explicit JOIN syntax. Simple rule: Never use commas in the FROM clause. Always use explicit JOIN with ON.
Then, you can solve your problem by including the subquery in the FROM clause:
SELECT ske.*, ske.amount + COALESCE(od.amount, 0) as poenb
FROM (SELECT k.id, s.fylke, s.Kommune, s.Skolenavn, k.schoolid,
k.number, k.letter, SUM(e.amount) as amount
FROM skoler s JOIN
klasser k
ON s.id = k.schoolid JOIN
etappe e
ON k.id = e.klasseid AND e.year = '2016'
GROUP BY k.id
) ske LEFT JOIN
(SELECT od.klasseid, SUM(od.poeng) as amount
FROM oppdrag od
GROUP BY od.klasseid
) od
ON od.klasseid = k.id
ORDER BY poeng;
Use explicit JOIN syntax. Also, include all columns that aren't aggregated in GROUP BY clause. Just because MySQL doesn't yield an error it doesn't mean that it's advisable to do it the way you did it. Not including all columns that aren't aggregated in a group by means picking random values.
SELECT
k.id,
s.fylke,
s.Kommune,
s.Skolenavn,
k.schoolid,
k.number,
k.letter,
COALESCE(SUM(e.amount), 0) + COALESCE(SUM(o.poeng), 0) AS poeng
FROM skoles AS s
INNER JOIN klasser AS k ON s.id = k.schoolid
INNER JOIN etappe AS e ON k.id = e.klasseid
LEFT JOIN ( SELECT klasseid, SUM(poeng) AS poeng FROM oppdrag ) AS o ON o.klasseid = k.id
WHERE e.year = '2016'
GROUP BY k.id, s.fylke, s.Kommune, s.Skolenavn, k.schoolid, k.number, k.letter
ORDER BY poeng

Slow SQL join on 5000 rows

I have ran into a problem when I tried to check if there was a difference in the results between different tests. The inner select statement returns around 5000 rows but the join doesn't finish in one minute. I expect the output to be around 10 rows. Any reason that the join is so slow?
select * from(
select *
from R inner join C
on R.i = C.j
where C.j in (2343,3423,4222,1124,2344)
) AS A,(
select *
from R inner join C
on R.i = C.j
where C.j in (2343,3423,4222,1124,2344)
) AS B
where A.x = B.x and
A.y = B.y and
A.result <> B.result
I think you can do what you want with aggregation:
select x, y, group_concat(distinct result) as results
from R inner join
C
on R.i = C.j
where C.j in (2343, 3423, 4222, 1124, 2344)
group by x, y
having count(distinct result) > 1;
For this query, an index on C(j) and R(i) would be very helpful. I would add x and y to the appropriate index as well, but I don't know which table they are combing from.

Order by total points per user_id descending

select
((select
COALESCE(sum(b.points_received), 0) as badge_total_points
from
user_badges ub
join
badges b ON ub.badge_id = b.badge_id
where
ub.user_id = '$user_id') + (select
COALESCE(sum(aps.given_points), 0) as total_action_points
from
user_action_points uap
join
action_point_system aps ON uap.point_id = aps.point_id
where
uap.user_id = '$user_id')) as total_contribution_points
how do I retrieve a list getting the total points grouped by a user_id with this SQL statement? Anybody have suggestions?
EDIT:
select
ub.user_id,
COALESCE(sum(b.isGold), 0) as gold_count,
COALESCE(sum(b.isSilver), 0) as silver_count,
COALESCE(sum(b.isBronze), 0) as bronze_count
from
user_badges ub
join
badges b ON ub.badge_id = b.badge_id
group by ub.user_id
how can I add this query to the result of the first question?
Although there are ways to do what you want, you can build on your existing query using correlated subqueries:
select u.*,
((select COALESCE(sum(b.points_received), 0) as badge_total_points
from user_badges ub join
badges b
ON ub.badge_id = b.badge_id
where ub.user_id = u.user_id
) +
(select COALESCE(sum(aps.given_points), 0) as total_action_points
from user_action_points uap join
action_point_system aps
ON uap.point_id = aps.point_id
where uap.user_id = u.user_id
)
) as total_contribution_points
from users u
order by total_contribution_points desc;

Unknown Column Left Join MySQL

I've used the "NOT IN (select)" Function, but it takes too long to load on several registers. So I want to improve the query using LEFT JOIN, but I don't know what's wrong. I'm getting #1054 - Unknown column 'a.id_logistica' in 'on clause'.
The column "id_logistica" in table "logistica" does exists, as it does in "det_log" table. This is the code:
SELECT
a.*, a.id_logistica,
b.nombre username, c.placa,
b.nombre scliente, e.nombre ruta,
d.nombre_con, clase
FROM
logistica a, cliente b,
vehiculo c, conductores d, ruta e
LEFT OUTER JOIN
det_log t2 ON t2.id_logistica = a.id_logistica
WHERE
a.id_cliente = b.id_cliente AND a.id_ruta = e.id_ruta
AND t2.id_logistica IS NULL AND a.id_vehiculo = c.id_vehiculo
AND a.id_conductor = d.id_conductor AND activo = 1
and finalizado = 0 AND ( a.id_ruta > 1 OR a.borrado = 9 )
ORDER BY
fecha_des DESC
if your query was running, you can try this one :
SELECT
a.*, a.id_logistica,
b.nombre username, c.placa,
b.nombre scliente, e.nombre ruta,
d.nombre_con, clase
FROM logistica a
Left Join cliente b On b.id_cliente = a.id_cliente
Left Join vehiculo c On c.id_vehiculo = a.id_vehiculo
Left Join conductores d On d.id_conductor = a.id_conductor
Left Join ruta e On e.id_ruta = a.id_ruta
Left Join det_log t2 On t2.id_logistica = a.id_logistica
WHERE ( a.id_ruta > 1 OR a.borrado = 9 )
And activo = 1
And finalizado = 0
And t2.id_logistica IS NULL
ORDER BY fecha_des DESC
but, if i look the error. it's mean nothing column "id_logistica" in table "logistica".
please check column in table "logistica".
desc logistica;
maybe, you wrong to write.

Cannot see mySQL COUNT from 3rd table

I have posted another message like this. But none helped. So I have done some more reading and I have this code which works to a point:
EDIT NEW VERSION & NEW ISSUE
SELECT i.*, o.organ_name, o.organ_logo, vtable.*
FROM heroku_056eb661631f253.op_ideas i
JOIN
(SELECT
COUNT(v.agree) as agree,
COUNT(v.disagree = 1 or null) as disagree,
COUNT(v.obstain = 1 or null) as abstain
FROM op_idea_vote v
) AS vtable
LEFT JOIN op_organs o ON i.post_type = o.organs_id
There is only 1 row in the op_idea_vote table, and 3 in the op_ideas table. But it's giving each row the total in each op_ideas row
EDIT WORKING SOLUTION
Thanks to WayneC, here is the working code:
SELECT i.*, o.organ_name, o.organ_logo, vtable.*
FROM heroku_056eb661631f253.op_ideas i
JOIN
(SELECT v.idea_Id,
COUNT(v.agree = 1 or null) as agree,
COUNT(v.disagree = 1 or null) as disagree,
COUNT(v.obstain = 1 or null) as abstain
FROM op_idea_vote v
GROUP BY v.idea_id
) AS vtable ON vtable.idea_id = i.idea_id
LEFT JOIN op_organs o ON i.post_type = o.organs_id
WHERE idea_geo = 'International';
Try this
SELECT i.*, o.organ_name, o.organ_logo, vtable.*
FROM heroku_056eb661631f253.op_ideas i
JOIN
(SELECT
COUNT(v.agree) as agree,
COUNT(v.disagree = 1 or null) as disagree,
COUNT(v.obstain = 1 or null) as abstain
FROM op_idea_vote v
GROUP BY v.idea_id
) AS vtable ON vtable.idea_id = i.idea_id
LEFT JOIN op_organs o ON i.post_type = o.organs_id
The answer below was missing the group by, and join condition for vtable
Here's your original query
SELECT i.*, o.organ_name, o.organ_logo
FROM heroku_056eb661631f253.op_ideas i
JOIN
(SELECT
COUNT(v.agree) as agree,
COUNT(v.disagree = 1 or null) as disagree,
COUNT(v.obstain = 1 or null) as abstain
FROM op_idea_vote v, op_ideas i
WHERE v.idea_id = i.idea_id
) AS vtable
LEFT JOIN op_organs o ON i.post_type = o.organs_id
vtable is a subquery masquerading as a table you're joining to - in terms of getting the fields to be returned with the query results, it's no different from joining a normal table. You have to select the fields you want returned in the main query, or they won't be returned.
SELECT i.*, o.organ_name, o.organ_logo, vtable.*
FROM heroku_056eb661631f253.op_ideas i
JOIN
(SELECT
COUNT(v.agree) as agree,
COUNT(v.disagree = 1 or null) as disagree,
COUNT(v.obstain = 1 or null) as abstain
FROM op_idea_vote v, op_ideas i
WHERE v.idea_id = i.idea_id
) AS vtable
LEFT JOIN op_organs o ON i.post_type = o.organs_id