I've got those tables
table1: GROUPS
grpID | name
--------------
1 | A
2 | B
3 | C
4 | D
5 | E
table2: USERS
userID | grpID | name
----------------------
1 |1 | nick
2 |1 | john
3 |1 | florans
4 |1 | keit
5 |1 | maria
6 |2 | ian
7 |2 | george
8 |2 | peter
9 |2 | bill
10 |2 | jonathan
11 |3 | jenifer
12 |3 | mina
13 |3 | ben
14 |3 | nick
15 |3 | john
16 |4 | florans
17 |4 | keit
18 |4 | maria
19 |4 | ian
20 |4 | george
21 |5 | peter
22 |5 | bill
23 |5 | jonathan
24 |5 | jenifer
25 |5 | mina
table3:POSTS
userID | posts
--------------
1 | 14
2 | 65
3 | 3
4 | 65
5 | 98
6 | 37
7 | 81
8 | 13
9 | 22
10 | 74
11 | 88
12 | 31
13 | 37
14 | 64
15 | 1
16 | 76
17 | 50
18 | 39
19 | 69
20 | 42
21 | 17
22 | 56
23 | 89
24 | 53
25 | 20
MySQL Fiddle
My goal is to get AVG (average) of the first 3 higher rows from every group. (or SUM of (max1, max2, max3) / 3 ).
Something like this:
grpID | max1 | max2 | max3 | AVG of max1, max2, max3
---------------------------------------------------------
1 98 65 65 76
5 89 56 53 66
4 76 69 50 65
2 81 74 37 64
3 88 64 37 63
and display it ORDER BY first 3 average DESC.
The final result will be like this:
grpID | first 3 higher rows Average
---------------------------------
1 |76
5 |66
4 |65
2 |64
3 |63
What i tried: (*** edited after Strawberry's comment)
SELECT GROUPS.grpID, GROUPS.name, AVG(POSTS.posts) AS PostsAVG
FROM USERS
INNER JOIN POSTS ON POSTS.userID = USERS.userID
INNER JOIN GROUPS ON GROUPS.grpID = USERS.grpID
GROUP BY GROUPS.grpID
ORDER BY PostsAVG DESC
The result i am getting with this is
grpID | name | PostsAVG
--------------------------------
4 | D | 55.2000
1 | A | 49.0000
5 | E | 47.0000
2 | B | 45.4000
3 | C | 44.2000
How can i get only the first three rows and not all 5 rows Average?
Can anyone help to solve this?
You could make use of variables to number the records in order of descending posts, per group. And then you could filter those on that row number ( < 4 ) to finally average those per group:
select grpid, avg(posts) as postavg
from ( select #rn := if(#grpid = grpid, #rn+1, 1) as rn,
#grpid := grpid as grpid,
posts
from ( select grpid, posts
from users1
inner join posts1
on posts1.userid = users1.userid
order by grpid, posts desc
) ordered,
( select #grpid := 0, #rn := 1) init
) numbered
where rn < 4
group by grpid;
http://rextester.com/HWR28741
Without variables
Without variables (and without the availability of window functions), you'd probably do best to create a function for this:
create function GetAveragePosts (grpid int)
returns float
return (select avg(posts)
from ( select posts
from users
inner join posts
on posts.userid = users.userid
where users.grpid = grpid
order by posts desc
limit 3
) topthree
);
And then the SQL itself is straightforward:
select grpid,
GetAveragePosts(grpid) as postsavg
from users
group by grpid
order by 2 desc
MySql fiddle outputs:
| grpID | postsavg |
|-------|----------|
| 1 | 76 |
| 5 | 66 |
| 4 | 65 |
| 2 | 64 |
| 3 | 63 |
Related
I want to get the unique data from multiple tables with the highest id
Refer below data
Users Table
id firstname_english
------ --------------------
2 Lama
4 Akram
6 Ammar
8 Basil
10 Sami
12 Hasan
14 Adnan
16 Mamoon
18 Sulaiman
20 Wasfi
22 Mervat
Users form status with their id
id users_id status_id
------ ----------- -----------
3 2 10
368 4 10
5 4 10
402 6 9
7 6 10
9 8 10
11 10 10
223 10 10
13 12 10
3253 14 2
15 14 10
17 16 10
1488 16 9
231 16 10
19 18 10
22 20 10
750 20 9
232 22 10
24 22 10
2935 22 9
297 22 10
The Result I need
id firstname_english status_id form_id
------ -------------------- --------------------
2 Lama 10 3
4 Akram 10 368
6 Ammar 9 402
8 Basil 10 8
10 Sami 10 223
12 Hasan 10 12
........and so on
I need to display the highest data from the table 2 with the matching id of table 1
For MySql 8.0+ use row_number() window function:
select
u.id, u.firstname_english,
f.status_id, f.id form_id
from users u inner join (
select *,
row_number() over (partition by users_id order by id desc) rn
from users_form
) f on f.users_id = u.id
where f.rn = 1
See the demo.
For previous versions of MySql:
select
u.id, u.firstname_english,
f.status_id, f.id form_id
from users u inner join (
select uf.* from users_form uf
where not exists (
select 1 from users_form
where users_id = uf.users_id and id > uf.id
)
) f on f.users_id = u.id
See the demo.
Results:
| id | firstname_english | status_id | form_id |
| --- | ----------------- | --------- | ------- |
| 2 | Lama | 10 | 3 |
| 4 | Akram | 10 | 368 |
| 6 | Ammar | 9 | 402 |
| 8 | Basil | 10 | 9 |
| 10 | Sami | 10 | 223 |
| 12 | Hasan | 10 | 13 |
| 14 | Adnan | 2 | 3253 |
| 16 | Mamoon | 9 | 1488 |
| 18 | Sulaiman | 10 | 19 |
| 20 | Wasfi | 9 | 750 |
| 22 | Mervat | 9 | 2935 |
I am stuck with some query logic. I have a table called student. Table have the marks of the student of each semester. There is n number of semesters. I need to get the name and id of students with highest maximum mark(mark1+mark2+mark3) in each semester.
This is my table structure
|id| name | mark1| mark2| mark3| sem|
|1 | Harry| 8 | 9 | 9 | 1 |
|2 | John | 10 | 8 | 10 | 1 |
|3 | Derek| 4 | 5 | 8 | 1 |
|4 | Dona | 8 | 9 | 5 | 1 |
|5 | Ammy | 9 | 9 | 9 | 2 |
|6 | Kate | 10 | 7 | 10 | 2 |
|7 | Aby | 3 | 5 | 4 | 2 |
|8 | Eliza| 5 | 9 | 5 | 2 |
Needed output
|id| name | mark1| mark2| mark3| sem| maxmark|
|2 | John | 10 | 8 | 10 | 1 | 28 |
|5 | Ammy | 9 | 9 | 9 | 2 | 27 |
|6 | Kate | 10 | 7 | 10 | 2 | 27 |
MY ATTEMPT TO GET maxmark
SELECT *, (MAX(`mark1` + `mark2` + `mark3`)) AS maxmark
FROM `stud`
GROUP BY `studid`
This query will give you the results you want. It JOINs the student table to a table filled with maximum marks for each semester, only showing students who achieved the maximum mark for that semester (s2.maxmark = s1.mark1+s1.mark2+s1.mark3).
SELECT s1.*, s2.maxmark
FROM student s1
JOIN (SELECT sem, MAX(mark1 + mark2 + mark3) AS maxmark
FROM student
GROUP BY sem) s2
ON s2.sem = s1.sem AND s2.maxmark = s1.mark1+s1.mark2+s1.mark3
Output:
id name mark1 mark2 mark3 sem maxmark
2 John 10 8 10 1 28
5 Ammy 9 9 9 2 27
6 Kate 10 7 10 2 27
SQLFiddle Demo
You have to group by sem to get the maximum marks for each sem in a sub query, once you have the max mark for each sem you could use a IN on a subquery like this,
SELECT *, mark1+mark2+mark3 AS maxmark
from student
where (sem, mark1 + mark2 + mark3) in (
SELECT sem, MAX(mark1 + mark2 + mark3) AS maxmark
FROM student
GROUP BY sem )
output
|id| name | mark1| mark2| mark3| sem| maxmark|
|2 | John | 10 | 8 | 10 | 1 | 28 |
|5 | Ammy | 9 | 9 | 9 | 2 | 27 |
|6 | Kate | 10 | 7 | 10 | 2 | 27 |
you could learn more about in from internet, https://www.techonthenet.com/mysql/in.php
good luck, hope this helped.
after two week search i couldn't write this query please help me
NOTE
TABLE 1 sum(quantity_box) group by id_p and id_w
TABLE 2 sum(quantity_box) group by id_p and id_w
then
TABLE1.sum(quantity_box)- TABLE2.sum(quantity_box) where id_p = id_p and id_w = id_w
table 1 ) wherehouseproduct_add id = id_w
id | name
10 | warehouse1
20 | warehouse2
table2) wherehouse_products
id | id_w |id_p |quantity_box
1 | 10 | 2 | 10
2 | 10 | 2 | 50
3 | 20 | 3 | 100
4 | 20 | 1 | 20
5 | 20 | 1 | 10
6 | 10 | 1 | 10
7 | 10 | 3 | 10
table3) wherehouse_products_sell
id | id_w |id_p |quantity_box
1 | 10 | 2 | 50
2 | 20 | 3 | 30
3 | 20 | 1 | 20
table4) products
id_p | product_name
1 | snack
2 | watebottle
3 | headphone
i want to output like
id_w | id_p | product_name| total_quantity_box
10 | 1 | snack |10
10 | 2 | watebottle |10
10 | 3 | headphone |10
20 | 1 | snack |10
20 | 2 | watebottle |10
20 | 3 | headphone |70
Calculate each type of sum individually in sub selects and join them as per your criteria then do your calculations in outer select
select wp.id_w,
wp.id_p,
wp.quantity - wps.quantity total_quantity_box
from
(select id_w,id_p,sum(quantity_box) quantity from wherehouse_products group by id_w,id_p) wp
join
(select id_w,id_p,sum(quantity_box) quantity from wherehouse_products_sell group by id_w,id_p) wps
using(id_w,id_p)
DEMO
Hi I have doubt in sql server
Table : patient
patientno | refdoctor| loccode | status | sdate
100 | 31 |10 | 1 | 2012-05-03
100 | 32 |10 | 1 |1997-02-04
100 | 36 |10 | 1 |2014-09-16
100 |35 |10 | 1 |2013-05-03
100 | 50 |10 | 1 | 1988-05-08
100 | 20 |10 | 2 |2015-02-05
Table : targetpatient
patientno | refdoctor| loccode | status | sdate
100 | 21 | 10 | 2 | 2004-05-18
100 | 23 | 10 | 2 |2005-07-25
100 | 24 | 10 | 2 | 2006-06-22
100 | 26 | 10 | 2 |2012-05-14
100 | 28 |10 | 2 |2013-05-03
100 |29 |10 | 2 | 2014-09-26
100 | 33 | 10 | 2 | 2012-10-22
100 | 39 | 10 | 2 |2002-12-13
100 |41 | 10 | 2 |2012-05-13
Here I want output patient table relates status
statusvalue=5's sdate is less than or equal to checkvalue=2's sdate and
the difference between the dates should be less than 30days then given count
if that condition not fall then count must be return zero(0)
select o.patientno,o.loccode,o.status,o.sDate, count(*) as cnt
from patient o join targetpatient t on o.patientno=t.patientno and o.loccode=t.loccode and o.status in('1') and t.status in('2') and
o.sDate<=t.sdate
and datediff(dd,o.sdate,t.sdate)<=30
group by o.patientno,o.loccode,o.status,o.sDate
based on above query I got result like below:
patientno | loccode | status | sdate | count
100 | 10 | 1 |2012-05-03 | 2
100 | 10 | 1 |2013-05-03 | 1
100 | 10 | 1 |2014-09-16 | 1
but I want expected result like below
patientno | loccode | status | sdate | count
100 | 10 | 1 |2012-05-03 | 2
100 | 10 | 1 |2013-05-03 | 1
100 | 10 | 1 |2014-09-16 | 1
100 | 10 | 1 | 1997-02-04 | 0
100 | 10 |1 | 1988-05-08 | 0
please tell me how to write query to achive this task in sql server .
If you want to include the records that doesn't have any matches in the joined table you'll want to use a left join instead and do the count on a column in the joined table instead like this:
select o.patientno,o.loccode,o.status,o.sDate, count(t.sdate) as cnt
from patient o
left join targetpatient t on o.patientno = t.patientno
and o.loccode = t.loccode
and o.status in('1')
and t.status in('2')
and o.sDate <= t.sdate
and datediff(dd,o.sdate,t.sdate) <= 30
group by o.patientno,o.loccode,o.status,o.sDate
A left join will return all rows from the table on the left side (patient in your case) plus the matching rows from the right-hand side table. The rows that doesn't have any matches in the right-hand side table will get null as values.
I would like to know how to do a Query in MySQL to get the remainder of the ID_COUNT / 8.
Here's an example table:
ID (INT) | PRODUCT ID | TIME
1 | 14 | 09:34:00
5 | 26 | 09:47:00
5 | 01 | 09:58:00
1 | 02 | 10:10:00
2 | 63 | 10:36:00
4 | 59 | 10:47:00
3 | 18 | 11:00:00
1 | 27 | 11:15:00
5 | 36 | 11:38:00
1 | 44 | 09:34:00
5 | 55 | 09:47:00
5 | 14 | 09:58:00
1 | 24 | 10:10:00
2 | 54 | 10:36:00
4 | 44 | 10:47:00
3 | 54 | 11:00:00
1 | 64 | 11:15:00
5 | 14 | 11:38:00
What i would like to do here is, every time a new row is inserted, I want to get the COUNT of that ID (for example for the ID=5 it would be 6), and them divide that number by 8 (6/8) and then get the remainder of that division.
I'm using PHP by the way, if there's no way of doing it only with MySQL.
Thanks in advance, any question fell free to ask!
Miguel.
Use MOD function
Query for you example
SELECT COUNT(1) MOD 8 AS result
FROM `table`
WHERE id=5
Query for common example
SELECT id, COUNT(1) MOD 8 AS result
FROM `table`
GROUP BY id
SELECT MOD(cnt, 8) FROM (SELECT COUNT(ID) cnt FROM mytable GROUP BY ID)
You can use the mod() function:
select mod(count(*), 8)
from t
where id = #Last_Id
The id is not auto incremented, so you cannot use last_inserted_id().