Error Trying to Use Temporary Columns, mysql - mysql

I am getting this error,
#1054 - Unknown column 'finalResult' in 'field list'
when ever I run this mysql query
SELECT userID, pickID, nflp_picks.gameID, visitorID, visitorResult, homeID, homeResult,
IF (pickID=visitorID, visitorResult, homeResult) AS finalResult,
IF (finalResult="Winner", 1, 0) AS Win
FROM nflp_picks, nflp_schedule
WHERE nflp_picks.gameID = nflp_schedule.gameID
ORDER BY gameID, pickID, userID
LIMIT 0, 200
Can I not use temporary columns?

You can't refer to aliases in the same query, except in GROUP BY, ORDER BY, and HAVING clauses. You can use a subquery:
SELECT *, (finalResult = "Winner") AS Win
FROM (SELECT userID, pickID, nflp_picks.gameID, visitorID, visitorResult, homeID, homeResult,
IF (pickID=visitorID, visitorResult, homeResult) AS finalResult
FROM nflp_picks
JOIN nflp_schedule
ON nflp_picks.gameID = nflp_schedule.gameID
ORDER BY gameID, pickID, userID
LIMIT 0, 200) x

Related

Is there a way to temporarily store a query result in mySQL?

So I've been trying to improve the complexity of this code. I searched through a lot of SO questions, but I think that's not what I wanted. I want to get 10 longest and shortest life expectancy countries - that's what the UNION is for. And as you can see there are two identical subqueries.
(SELECT *
FROM
(SELECT name, life_expectancy
FROM country_info
WHERE life_expectancy!="null") AS life_expectancy_table
ORDER BY life_expectancy DESC
LIMIT 10)
UNION
(SELECT *
FROM
(SELECT name, life_expectancy
FROM country_info
WHERE life_expectancy!="null") AS life_expectancy_table
ORDER BY life_expectancy
LIMIT 10)
I suspect that the subquery is being run 2 times and that is the thing I want to avoid. Moreover, even if the query is not being run 2 times, I would like to use an alias to improve readability.
Your query is a fine method, but doesn't require so many subqueries:
(SELECT name, life_expectancy
FROM country_info
WHERE life_expectancy <> 'null'
ORDER BY life_expectancy DESC
LIMIT 10
) UNION -- intentional to remove duplicates
(SELECT name, life_expectancy
FROM country_info
WHERE life_expectancy <> 'null'
ORDER BY life_expectancy
LIMIT 10
);
It seems very strange that life_expectancy would be stored as a string. You may intend life_expectancy IS NOT NULL.
You can also do this with window functions:
SELECT name, life_expectancy
FROM (SELECT ci.*,
ROW_NUMBER() OVER (ORDER BY life_expectancy DESC) as seqnum_desc,
ROW_NUMBER() OVER (ORDER BY life_expectancy ASC) as seqnum_asc
FROM country_info ci
WHERE life_expectancy <> 'null'
) t
WHERE seqnum_desc <= 10 OR seqnum_asc <= 10;

MYSQL row sequence with SUM() and ORDER BY

I try to order my rows by user's total point.
SUM and ORDER BY working correctly. But also i want to add sequence numbers of rows.
When I try to use #row_number I get some numbers but sequence is incorrect.
correct num column order should be 1,2,3,4 because I use order by total_point of sum of user's points.
How can I get correct sequence for num column?
SELECT
users.user_id,
users.user_hash,
(#row_number:=#row_number + 1) AS num,
sum(total_point) as total_point
FROM (SELECT #row_number:=0) AS t,user_stats
LEFT JOIN users on users.user_id = user_stats.stats_user_id
WHERE create_date BETWEEN "2020-04-01 00:00:00" AND "2020-04-30 23:59:59"
GROUP BY stats_user_id
ORDER BY total_point DESC
v: mysql 5.7
You must use the with total sorted rows and give them a number
SELECT
user_id,
user_hash,
users.user_nick,
(#row_number:=#row_number + 1) AS num,
total_point
FROM
(SELECT
users.user_id,
users.user_hash,
users.user_nick,
SUM(total_point) AS total_point
FROM
user_stats
LEFT JOIN users ON users.user_id = user_stats.stats_user_id
WHERE
create_date BETWEEN '2020-04-01 00:00:00' AND '2020-04-30 23:59:59'
GROUP BY stats_user_id
ORDER BY total_point DESC) t1,
(SELECT #row_number:=0) AS t
ORDER BY num ASC;

Translate Lead/Lag function to MySQL

How do I translated the below codes so that it runs in MySQL. I am new to MySQL and finding it difficult to understand few things.
CODE 1:
SELECT t1.user_id,
t1.visit_month LEAD (t1.visit_month, 1) OVER (partition BY t1.user_id ORDER BY t1.user_id, t1.visit_month)
FROM (SELECT
user_id,
month(date_time) as visit_month
FROM
tbl_activity
group by 1, 2
ORDER BY 1 , 2) t1;
Desired Output for Code 1
CODE 2:
SELECT user_id,
visit_month,
lead,
lead — visit_month AS time_diff
FROM table3
CODE 3:
SELECT user_id,
Visit_month,
lag(visit_month, 1) over (partition BY user_id ORDER BY user_id, visit_month)
FROM table
CODE 4:
SELECT user_id,
visit_month,
lag,
visit_month — lag AS time_diff
FROM table2
You could express the lead() and lag() function via subquery
select user_id, month(date_time) as visit_month,
month(date_time)-(select month(date_time) from tbl_activity
where user_id = a.user_id and
month(date_time) < month(a.date_time)
order by month(date_time) desc LIMIT 1) as time_diff -- This could be re-express via lag() function
from tbl_activity a
group by user_id, month(date_time);
In above you would need to just specify < / > to express the lead() and lag() functionality in subquery and don't forget to use order by clause
EDIT (Lead) :
select user_id, month(date_time) as visit_month,
(select month(date_time) from tbl_activity
where user_id = a.user_id and
month(date_time) > month(a.date_time)
order by month(date_time) LIMIT 1) as lead -- This could be re-express via lead() function
from tbl_activity a
group by user_id, month(date_time);

MySQL FROM Subquery with parent group by

I need to show a ranking lists for a sport we manage.
It needs to sum up the 4 best results for each player (from a table that could have hundreds of results per player) and then sort the entire list from the player with the most points to least points.
The query below returns
ERROR 1054 (42S22): Unknown column 'r1.user_id' in 'where clause'
so I've gone off track somewhere.
SELECT r1.user_id, (
SELECT SUM(points)
FROM (
SELECT *
FROM ranking_matrix_points r2
WHERE user_id=r1.user_id
ORDER BY points DESC
LIMIT 4
) r3
) AS total_points
FROM ranking_matrix_points r1
WHERE
user.status IN('active')
GROUP BY r1.user_id
ORDER BY total_points DESC
One possible solution might be to number the rows for each user in order of points descending and then sum up the points with a rank <= 4. This might not perform very well though, and also you'll get a problem with ties (but you would have using limit too).
select user_id, sum(points) total_points
from (
select user_id, points,
(
case user_id
when #cur_user
then #row := #row + 1
else #row := 1 and #cur_user := user_id end
) as rank
from ranking_matrix_points,
(select #row := 0, #cur_user := '') r
order by user_id, points desc
) t
where rank <= 4
group by user_id;
I'm pretty sure there are better ways to do this but I can't think of any at the moment. This would have been very easy in just about any database with support for window functions, but sadly MySQL doesn't support any yet.
You don't need a double query, just
SELECT user_id, SUM(points)
FROM ranking_matrix_points
WHERE user.status in('active')
GROUP BY user_id
ORDER BY total_points DESC
LIMIT 4
or
SELECT TOP 4 user_id, SUM(points)
FROM ranking_matrix_points
WHERE user.status in('active')
GROUP BY user_id
ORDER BY total_points DESC

Select count from multiple tables and group by

Help me!
$sql = SELECT `id`, `email`, `avatar`,`fullname`,
SUM(result) as sum_result,
SUM(total) as sum_total,
COUNT(rank) as `top_1` where `itq_exam_thread_test`.`rank` = 1,
COUNT(rank) as `top_2` where `itq_exam_thread_test`.`rank` = 2,
COUNT(rank) as `top_3` where `itq_exam_thread_test`.`rank` = 3
GROUP BY userid_created
ORDER BY sum_result DESC, sum_rate DESC
LIMIT 0, 100';
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'where itq_exam_thread_test.rank = 1,
WHERE is a clause for the entire query, not a modifier in the SELECT clause. What you want is conditional aggregation. In MySQL, doing the count is quite easy, because it treats boolean expressions as integers in a numeric context. So, you can just use SUM():
SELECT id, email, avatar, fullname, SUM(result) as sum_result,
SUM(total) as sum_total,
SUM(rank = 1) as top_1,
SUM(rank = 2) as top_2,
SUM(rank = 3) as top_3
FROM itq_exam_thread_test
GROUP BY userid_created
ORDER BY sum_result DESC
LIMIT 0, 100;
I removed sum_rate from the ORDER BY, because it is not defined.