I need to display progressive_total using mysql.
I have a table look like this:
id value cumulative_total
1 100 100
2 150 250
3 200 450
4 300 750
I want to add a new column called progressive_total, so the table would look like this:
id value Progressive_total cumulative_total
1 100 - 100
2 150 100 250
3 200 250 450
4 300 450 750
I use the below mysql query to display the Cumulative total:
SELECT t.id, t.value,
(SELECT SUM(x.value) FROM house_details x WHERE x.id <= t.id) AS cumulative_total
FROM house_details t
WHERE t.income IS NOT NULL AND t.income!= '' AND YEAR(t.cdate) = YEAR(CURRENT_DATE())
ORDER BY t.id
The above query works fine and getting cumulative_total. But i want to display progressive_total also, like i have given in the example.
SELECT t.id, t.value,
IFNULL((SELECT SUM(x.value) FROM house_details x WHERE x.id < t.id), '-') AS progressive_total,
(SELECT SUM(x.value) FROM house_details x WHERE x.id <= t.id) AS cumulative_total
FROM house_details t
WHERE t.income IS NOT NULL AND t.income!= '' AND YEAR(t.cdate) = YEAR(CURRENT_DATE())
ORDER BY t.id
You can use variables:
SELECT t.id, t.value,
#s := #s +IF(#temp := #prev,
IF(#prev := t.value, #temp, #temp),
IF(#prev := t.value, #temp, #temp)) AS progressive_total,
(SELECT SUM(x.value)
FROM house_details x
WHERE x.id <= t.id) AS cumulative_total
FROM house_details t
CROSS JOIN (SELECT #s := 0, #prev := 0, #temp := 0) AS v
WHERE t.income IS NOT NULL and t.income!= '' AND
YEAR(t.cdate) = YEAR(CURRENT_DATE())
order by t.id
Variable #prev is set to the value of the immediately preceding row. We have to use an intermediate variable like #temp, to hold the value of #prev, before #prev is set to its new value.
Demo here
Edit: The above query can be simplified to:
SELECT id, value,
#ps := #ps + prev AS progressive_total,
#cs := #cs + value AS cumulative_total
FROM (
SELECT t.id, t.value,
IF(#temp := #prev,
IF(#prev := t.value, #temp, #temp),
IF(#prev := t.value, #temp, #temp)) AS prev
FROM house_details t
CROSS JOIN (SELECT #s := 0, #prev := 0, #temp := 0) AS v
WHERE t.income IS NOT NULL and t.income!= '' AND
YEAR(t.cdate) = YEAR(CURRENT_DATE())
ORDER BY t.id) AS x
CROSS JOIN (SELECT #ps := 0, #cs := 0) AS u
ORDER BY id
Demo here
Related
Need to find median value of time difference between sent date and click date (in seconds) for each type of emails. I found solution just for all data:
SET #rowindex := -1;
SELECT g.type, g.time_diff
FROM
(SELECT #rowindex:=#rowindex + 1 AS rowindex,
TIMESTAMPDIFF(SECOND, emails_sent.date_sent, emails_clicks.date_click) AS time_diff,
emails_sent.id_type AS type
FROM emails_sent inner join emails_clicks on emails_sent.id = emails_clicks.id_email
ORDER BY time_diff) AS g
WHERE g.rowindex IN (FLOOR(#rowindex / 2) , CEIL(#rowindex / 2));
Is it possible to add group by id_type statement?
Thanks!
First, you need to enumerate the rows for each type. Using variables, this code looks like:
select sc.*,
(#rn := if(#t = id_type, #rn + 1,
if(#t := id_type, 1, 1)
)
) as seqnum
from (select timestampdiff(second, s.date_sent, c.date_click) as time_diff,
s.id_type,
from emails_sent s inner join
emails_clicks c
on s.id = c.id_email
order by time_diff
) sc cross join
(select #t := -1, #rn := 0) as params;
Then, you need to bring in the total number for each type and do the calculation for the median:
select sc.id_type, avg(time_diff)
from (select sc.*,
(#rn := if(#t = id_type, #rn + 1,
if(#t := id_type, 1, 1)
)
) as seqnum
from (select timestampdiff(second, s.date_sent, c.date_click) as time_diff,
s.id_type,
from emails_sent s inner join
emails_clicks c
on s.id = c.id_email
order by time_diff
) sc cross join
(select #t := -1, #rn := 0) as params
) sc join
(select id_type, count(*) as cnt
from emails_sent s inner join
emails_clicks c
on s.id = c.id_email
group by id_type
) n
where 2 * seqnum in (n.cnt, n.cnt, n.cnt + 1, n.cnt + 2)
group by sc.id_type;
I have mysql table called ware_stock_transaction and it has order_no, order_type, created_date, item_no.
I want to get the last 10 record from each item, like this:
item A (10 records)
item B (10 records)
item C (10 records)
In MySQL, you can use variables:
select wst.*
from (select wst.*,
(#rn := if(#i = item_no, #rn + 1,
if(#i := item_no, 1, 1)
)
) as rn
from ware_stock_transaction wst cross join
(select #rn := 0, #i := '') params
order by item_no, created_date desc
) wst
where rn <= 10;
My first query
SELECT
id,
year_,
month_
FROM
(SELECT
tp.id,
YEAR(FROM_UNIXTIME(tp.visited_date)) as year_,
MONTH(FROM_UNIXTIME(tp.visited_date)) as month_,
#rn := IF(#prev = CONCAT(YEAR(FROM_UNIXTIME(tp.visited_date)),MONTH(FROM_UNIXTIME(tp.visited_date))), #rn + 1, 1) AS rn,
#prev := CONCAT(YEAR(FROM_UNIXTIME(tp.visited_date)),MONTH(FROM_UNIXTIME(tp.visited_date)))
FROM
tr_place tp
JOIN
(SELECT #prev := NULL, #rn := 0) AS vars
ORDER BY
YEAR(FROM_UNIXTIME(tp.visited_date)) DESC,
MONTH(FROM_UNIXTIME(tp.visited_date)) DESC) AS T1
WHERE
rn < 3;
Will returns the data set This is the result which I got from the query
The subquery in it
SELECT
tp.id,
YEAR(FROM_UNIXTIME(tp.visited_date)) as year_,
MONTH(FROM_UNIXTIME(tp.visited_date)) as month_,
#rn := IF(#prev = CONCAT(YEAR(FROM_UNIXTIME(tp.visited_date)),MONTH(FROM_UNIXTIME(tp.visited_date))), #rn + 1, 1) AS rn,
#prev := CONCAT(YEAR(FROM_UNIXTIME(tp.visited_date)),MONTH(FROM_UNIXTIME(tp.visited_date)))
FROM
tr_place tp
JOIN
(SELECT #prev := NULL, #rn := 0) AS vars
ORDER BY
YEAR(FROM_UNIXTIME(tp.visited_date)) DESC,
MONTH(FROM_UNIXTIME(tp.visited_date)) DESC;
Returns data The sub query will returns this data
I need the subquery's greatest rn as a column in the first query.
How can I achieve that?
You may be having a problem with variable assignment. You should not be referencing variables in multiple expressions in the select. So, the correct way to write the first query is:
SELECT id, year_, month_
FROM (SELECT tp.id,
YEAR(FROM_UNIXTIME(tp.visited_date)) as year_,
MONTH(FROM_UNIXTIME(tp.visited_date)) as month_,
(#rn := IF (#prev = CONCAT(YEAR(FROM_UNIXTIME(tp.visited_date)), MONTH(FROM_UNIXTIME(tp.visited_date))), #rn,
if(#prev := CONCAT(YEAR(FROM_UNIXTIME(tp.visited_date)), MONTH(FROM_UNIXTIME(tp.visited_date))), 1, 1
)
) as rn
FROM tr_place tp JOIN
(SELECT #prev := NULL, #rn := 0) AS vars
ORDER BY YEAR(FROM_UNIXTIME(tp.visited_date)) DESC,
MONTH(FROM_UNIXTIME(tp.visited_date)) DESC
) t1
WHERE rn < 3;
Note the variable assignments are all in a single expression.
This may fix your issue.
ok i have this query from (Mr.Austin):
SELECT
IF(is_real, '**ANY WORD**', full_name) AS full_name,
IF(is_real, '', club_name) AS club_name
FROM
(
SELECT
full_name,
club_name,
(#row_num2:= #row_num2 + 1) AS row_num
FROM
(
SELECT p3.*
FROM
(
SELECT
p2.*,
(#row_num := #row_num + 1) AS row_num
FROM
(
SELECT *
FROM players AS p1
WHERE y_of_birth = 2000
) AS p2
CROSS JOIN
(
SELECT
#row_num := 0,
#count := (SELECT COUNT(*) FROM players WHERE y_of_birth = 2000)
) AS vars
ORDER BY club_name
) AS p3
ORDER BY row_num % FLOOR(#row_num / 2), row_num
) AS p4
CROSS JOIN
(
SELECT
#row_num2 := -1,
#extra := GREATEST(2, POW(2, CEIL(LOG2(#count)))) - #count) AS vars
) AS data
LEFT JOIN
(
(SELECT 1 AS is_real)
UNION ALL
(SELECT 0 AS is_real)
) AS filler
ON
MOD(row_num, FLOOR(#count / #extra)) = 0 AND
row_num / FLOOR(#count / #extra) < #extra
ORDER BY row_num, is_real
it works well and there are no adjacency between two similar club_name but the problem is when i have large result of query for example 214 player it gave me many iterative between the same different club_name for example El-ahly vs Ismaily then again El-ahly vs Ismaily then again El-ahly vs Ismaily then repeat again with wadi dgla vs Cocorico then again wadi dgla vs Cocorico then again wadi dgla vs Cocorico why this iteration happened and how can i fix this problem ? can i make this iteration happens is there anyway to solve this problem to be one or two maximum times the native query of no adjacency between two similar club name is from (Mr.Gordon Linoff):
select p.*
from (select p.*,
(#rn := if(#c = club_name, #rn + 1,
if(#c := club_name, 1, 1)
)
) as rn
from players p cross join
(select #rn := 0, #c := '') params
order by club_name
) p join
(select club_name, count(*) as cnt
from players p
group by club_name
) pc
on p.club_name = pc.club_name
order by rn * (#rn / cnt);
sqlfiddle:
sqlfiddle
How can I limit result per each id in WHERE clause?
My query is:
SELECT name
FROM location_areas
WHERE parent IN ("1,2,3")
ORDER BY popularity,name
Parent is not unique.
I need to get 10 results for each parent id in WHERE clause.
for example table structure is:
id name parent
1 name 0
2 name 1
3 name 1
4 name 80
5 name 80
6 name 80
7 name 80
8 name 1
Try this:
SELECT
T.name,
T.popularity,
T.parent,
T.rank
FROM
(
SELECT
L.name,
L.popularity,
L.parent,
#rank := IF(#parent = parent, #rank + 1, 1) rank,
#parent := parent
FROM location_areas L,
(SELECT #rank := 1, #parent := NULL) R
) T
WHERE T.rank <= 10
EDIT
SELECT T.name, T.popularity, T.parent, T.level, T.rank
FROM (
SELECT L.name, L.popularity,
L.parent, L.level,
#rank := IF(#parent = parent, #rank + 1, 1) rank,
#parent := parent
FROM location_areas L,
(SELECT #rank := 1, #parent := NULL) R
WHERE L.parent IN (".$ids.")
) T WHERE T.rank <= 10;
You can simply do it lie this
SET #level = 0;
SET #group = '';
SELECT
name
FROM (
SELECT
name ,
parent
#level := IF(#group = parent, #level+1, 1) AS level,
#group := parent as EGroup
FROM test
WHERE parent IN ("1,2,3")
ORDER BY parent
) rs
WHERE level < 11