MySQL: Select top 5 rows based on ID and find Subtotal - mysql

Need to select top 5 rows for each id based on desc values of a particular column , value and find the subtotal of that column . for e.g (Tried creating the situation , actual table structure is large )
ID VALUE
1 2
1 3
1 4
1 5
1 6
1 7
1 8
2 9
2 10
2 11
2 12
2 13
2 14
Output Expected
ID VALUE
1 8
1 7
1 6
1 5
1 4
TOTAL 30
2 14
2 13
2 12
2 11
2 10
TOTAL 60
I could select top 5 rows using a code like this ;
#cust_rank := IF(#current_cust = id, #cust_rank + 1, 1) AS cust_rank,
#current_cust := id
and then selecting top 5
Also ,I could subtotal using code like this ;
SELECT id, value FROM source
UNION
SELECT NULL,SUM(value) FROM source
GROUP BY id ORDER BY id;
I need to merge both requirements .

SELECT CAST(id as CHAR(50)) Id, value
FROM (SELECT id , value ,
IF(#lastid=(#lastid:=id), #auto:=#auto+1, #auto:=1) indx
FROM source, (SELECT #lastid:=0, #auto:=1) A
ORDER BY id,value desc)as A
WHERE indx <= 5
Output
Id value
1 8
1 7
1 6
1 5
1 4
2 14
2 13
2 12
2 11
2 10
2nd Query
SELECT 'Total', SUM(value)
FROM (SELECT id , value ,
IF(#lastid=(#lastid:=id), #auto:=#auto+1, #auto:=1) indx
FROM source, (SELECT #lastid:=0, #auto:=1) A
ORDER BY value desc)as A
WHERE indx <= 5
GROUP BY id ;
Output
Total SUM(value)
Total 30
Total 60
Merged Query:
Select
CASE
WHEN indx =6 THEN "Total"
ELSE id
END as ID,value
from
(
select id,value,
IF(#lastid=(#lastid:=id), #auto:=#auto+1, #auto:=1) indx
FROM
(
SELECT CAST(id as CHAR(50)) Id, value
FROM (SELECT id , value ,
IF(#lastid=(#lastid:=id), #auto:=#auto+1, #auto:=1) indx
FROM source, (SELECT #lastid:=0, #auto:=1) A
ORDER BY id,value desc)as A
WHERE indx <= 5
UNION
SELECT CAST(id as CHAR(50))as id, SUM(value)as value
FROM (SELECT id , value ,
IF(#lastid1=(#lastid1:=id), #auto1:=#auto1+1, #auto1:=1) indx
FROM source, (SELECT #lastid1:=0, #auto1:=1) A
ORDER BY value desc)as A
WHERE indx <= 5
GROUP BY id)as output ,(SELECT #lastid:=0, #auto:=1) A ORDER BY id) as output1
Output
ID value
1 8
1 7
1 6
1 5
1 4
Total 30
2 10
2 11
2 12
2 13
2 14
Total 60

Related

get last completed (some condition) id while counting

I'm trying to get the last completed task id of the child table while counting all the child records and completed child records:
set #tmp := 0;
select
count(*) total,
count(if(completed=1, 1, null)) completed,
#tmp:=if(completed=1, task_id, #tmp) last_completed_task_id
from child_table where parent_id = 6
order by sequence
Here is some sample data:
id parent_id completed task_id sequence
526 6 1 1 1
1653 6 0 5 2
2749 6 0 20 3
3840 6 0 21 4
4913 6 1 22 5
5983 6 0 23 6
7063 6 0 25 7
7183 6 0 26 8
8241 6 1 27 9
9317 6 0 28 10
10380 6 0 29 11
So final result should be like that:
total: 11
completed: 3
last_completed_task_id: 27
I know how to get it with separate queries, but I wish to get it with one query if possible.
You could use a cros join between the count and the max task_id eg:
select
count(*) total,
count(if(completed=1, 1, null)) completed,
t.last_completed_task_id
from child_table
cross join (
select max(task_id) last_completed_task_id
from child_table
where parent_id = 6
and completed=1 ) t
where parent_id = 6
You can easily get the last completed id using conditional aggregation:
select count(*),
sum(is_completed = 1),
max(case when is_completed = 1 then id end) as last_completed_id
from child_table ct
where parent_id = 6;
If task_id is increasing -- as in your sample data -- you can just use task_id rather than id in the max().
Otherwise, just join the table back in:
select cnt, cnt_completed, ct2.task_id
from (select count(*) as cnt,
sum(is_completed = 1) as cnt_completed,
max(case when is_completed = 1 then id end) as last_completed_id
from child_table ct
where parent_id = 6
) x join
child_table ct2
on x.last_completed_id = ct2.id
You could try this :
select count(*) total,
count(if(completed=1, 1, null)) completed,
(select task_id from child_table where parent_id = 6 and completed = 1 order by sequence desc limit 1) as last_completed_task_id
from child_table
where parent_id = 6

I have table containing names and I want to show the output sorted alphabetically but I want to show only 2 record of each alphabet

Table
Id name
1 Akhil
2 Akira
3 Anuj
4 Bia
5 Bina
6 Chetu
7 Chini
8 Chikna
9 Chana
Output
Id name
1 Akhil
2 Akira
3 Bia
4 Bina
6 Chetu
7 Chini
Here the Query. In the Result are more field, but you can remove them. They are only to see how the Query works
SELECT * FROM (
SELECT
#nr := IF(#old_val = SUBSTRING(t.name,1,1),(#nr +1),1) AS nr,
#old_val:=SUBSTRING(t.name,1,1) AS tmp,
t.name FROM mytable t,
(SELECT #nr:=0, #old_val:='') AS TMP
ORDER BY NAME
) AS result WHERE nr < 3;
Please let me know if it works for you

How to fetch specific number of row on basis of score

Have to show on specific count . Means i have to show max score value 4 times then less than that score to 3 times and so on
I have table like:-
ID Score
1 1
2 1
3 1
4 1
5 2
6 2
7 2
8 3
9 3
10 4
11 4
12 4
and I am expecting output like:-
Score
1
1
1
2
2
3
4
Try this:
SELECT Score
FROM
(SELECT a.Score, a.ID, count(*) as RN FROM TableName a
JOIN TableName b ON a.Score = b.Score AND a.ID >= b.ID
GROUP BY a.Score, a.ID) T
WHERE RN>1
Result:
SCORE
1
1
1
2
2
3
4
4
An example in SQL Fiddle.
Explanation:
In the inner query, we are selecting a row number partitioned by ID and order by score. And then we select Score from the inner query whose Row number is greater than 1 (inorder to omit 1 record).
SELECT x.*
FROM my_table x
JOIN my_table y
ON y.marks = x.marks
AND y.id <= x.id
GROUP
BY x.marks
, x.id
HAVING COUNT(0) <= MAX(4-x.marks)
ORDER
BY marks DESC,id;

How to make a fake column with an autoincrement number in a "group by" query

I have data in a table like this:
fgid qty ntid
1 100 10
2 90 10
6 200 11
1 80 11
1 120 12
6 100 12
6 30 13
And i make query :
SELECT fgid, SUM(qty) AS total_qty, COUNT(ntid) AS nt_count FROM sofg
GROUP BY fgid
AND the result is :
fgid total_qty nt_count
1 300 3
2 90 1
6 330 3
Then i want to make the result like this :
no fgid total_qty nt_count
1 1 300 3
2 2 90 1
3 6 330 3
How to do that with a query? where 'no' is (like) autoincrement number.
Try this query.
SELECT
#rownum := #rownum + 1 rownum,
t.*
FROM (SELECT #rownum:=0) r,
(
SELECT fgid, SUM(qty) AS total_qty, COUNT(ntid) AS nt_count FROM sofg GROUP BY fgid
) t;
Basically the same as Dhinakaran's answer, but there's no need to put the whole main query into a subquery. There's no difference to his answer appart from maybe being more pleasing to the eye, but please accept Dhinakaran's answer, as he was faster.
SELECT
#rownum:=#rownum + 1 as rownumber,
fgid,
SUM(qty) AS total_qty,
COUNT(ntid) AS nt_count
FROM sofg
, (select #rownum:=0) v
GROUP BY fgid

SQL query "Find the article that has generated most income?"

I want to make a SQL query that shows me the article that generated most income. (in a shop)
Table = orderrader
rownumber articlenumber ordernumber price amount
1 11 1 8624 3
2 6 1 4794 2
3 17 1 8755 3
4 1 1 7803 1
5 16 1 8987 3
6 10 1 4575 3
7 4 1 8747 1
8 15 1 5439 3
9 11 2 8624 3
10 1 2 7803 1
Following sql statement will return only one articlenumber with max revenue.
Select articlenumber, sum(price*amount) as totalincome
from orderrader
group by articlenumber
order by sum(price*amount) desc LIMIT 1
SELECT articlenumber
FROM orderrader
WHERE (price * amount) = (SELECT MAX(price * amount) FROM orderrader)
This should do the trick, i checked it on my own database. It will give ONLY the one with the highest price*amount
SELECT articlenumber, SUM(price*amount) AS income
FROM table
GROUP BY articlenumber
ORDER BY income DESC
select articlenumber, sum(price*amount) as s from orderrader group by articlenumber order by s desc;