Getting required rows in mysql using GROUPBY - mysql

I have a table named travel which is as follows:
+-------+-----+----------+
| Name | Day | Distance |
+-------+-----+----------+
| Ravi | 1 | 10 |
| Ravi | 2 | 21 |
| Ravi | 3 | 23 |
| Hari | 1 | 12 |
| Hari | 2 | 32 |
| Kiran | 1 | 12 |
| Kiran | 2 | 32 |
| Kiran | 3 | 21 |
| Kiran | 4 | 43 |
+-------+-----+----------+
using group in sql for this table as
select name, day, distance, sum(distance) as total_dist
from travel
group by name;
I get the result as follows
+-------+-----+----------+------------+
| Name | Day | Distance | total_dist |
+-------+-----+----------+------------+
| Ravi | 1 | 10 | 54 |
| Hari | 1 | 12 | 44 |
| Kiran | 1 | 12 | 108 |
+-------+-----+----------+------------+
That is mysql gives the top row by default for columns which are not aggregated. But I would prefer to get all the rows with aggregated values or rows with bottom row in the group like as follows:
+-------+-----+----------+------------+
| Name | Day | Distance | total_dist |
+-------+-----+----------+------------+
| Ravi | 3 | 23 | 54 |
| Hari | 2 | 32 | 44 |
| Kiran | 4 | 43 | 108 |
+-------+-----+----------+------------+
or either in this way:
+-------+-----+----------+------------+
| Name | Day | Distance | total_dist |
+-------+-----+----------+------------+
| Ravi | 1 | 10 | 54 |
| Ravi | 2 | 21 | 54 |
| Ravi | 3 | 23 | 54 |
| Hari | 1 | 12 | 44 |
| Hari | 2 | 32 | 44 |
| Kiran | 1 | 12 | 108 |
| Kiran | 2 | 32 | 108 |
| Kiran | 3 | 21 | 108 |
| Kiran | 4 | 43 | 108 |
+-------+-----+----------+------------+
I am new to using mysql and confused with using group by, please guide me if any of the above two results are possible to get.

To get the entire list with the sum for each group, you can use a subquery and join the total back to the original table:
select t.name, t.day, t.distance, t2.total_dist
from travel t
join (select name, sum(distance) total_dist
from travel
group by name) t2 on t.name = t2.name
SQL Fiddle Demo
Or to get the max day per group, just include max(day) in the subquery:
select t.name, t.day, t.distance, t2.total_dist
from travel t
join (select name, sum(distance) total_dist, max(day) max_day
from travel
group by name) t2 on t.name = t2.name and t.day = t2.max_day
More Fiddle

it will work for you
select name,max(day),max(distance)
from tablename
group by name
and other case
select name,max(day),max(distance),(select sum(distance) from table) as total_dist
from tablename
group by name

Related

How to use SUM with DISTINCT function togather

Is there any way by which i can SUM(value) of ColA (ColA is repeating in each ROW) based on DISTINCT(value) of ColB?
My Data Table is:
+-------+-------+------+--------+
| State | KEY_ID| Score| STATUS |
+-------+-------+------+--------+
| ABCD | 11 | 20 | 1 |
| ABCD | 11 | 30 | 1 |
| ABCD | 13 | 40 | 1 |
| DEFG | 21 | 10 | 1 |
| DEFG | 21 | 25 | 1 |
| DEFG | 23 | 15 | 1 |
+-------+-------+------+--------+
& wanted output like :
+-------+-------+------+--------+
| State | KEY_ID| Score| STATUS |
+-------+-------+------+--------+
| ABCD | 11 | 50 | 1 |
| ABCD | 13 | 40 | 1 |
| DEFG | 21 | 35 | 1 |
| DEFG | 23 | 15 | 1 |
+-------+-------+------+--------+
but not want to use GROUP BY function & OVER() in not working in my MySQL version 8.0.28
You want a simple GROUP BY query to aggregate your scores. fiddle.
SELECT State, KEY_ID,
SUM(Score) Score,
STATUS
FROM mytable
GROUP BY State, KEY_ID, STATUS
You can use GROUP_BY (https://www.w3schools.com/sql/sql_groupby.asp) on KEY_ID
like this query
SELECT State, KEY_ID, SUM(Score), STATUS FROM data_table GROUP BY KEY_ID;

MYSQL adding columns value of rows

I have a problem in which I have a STUDENT table as
+-------------+-------------+-------------+-------------+---------------+
| roll_number | name | subject_one | subject_two | subject_three |
+-------------+-------------+-------------+-------------+---------------+
| 1 | Sheila | 32 | 48 | 64 |
| 2 | Rachel | 24 | 21 | 25 |
| 3 | Christopher | 55 | 12 | 10 |
+-------------+-------------+-------------+-------------+---------------+
I want the print the output as
+-------------+-------------+-------------+
| roll_number | name | total |
+-------------+-------------+-------------+
| 1 | Sheila | 144|
| 2 | Rachel | 70 |
| 3 | Christopher | 77 |
+-------------+-------------+-------------+
and select all student having marks greater than 75 ??
How can I achieve this using MYSQL ??
I think you just need the aggregate functions and using them is enough. I am not sure if it can help you or not.
SELECT roll_number , name , (subject_one + subject_two + subject_three) AS total FROM STUDENT HAVING total > 75 ;

sql joins with multiple conditions

i have two tables, (say bill and soldproduct)
select * from bill;
+------+------------+------------+
| id | solddate | customerId |
+------+------------+------------+
| 11 | 2018-07-23 | 1 |
| 12 | 2018-07-21 | 1 |
| 13 | 2018-08-02 | 2 |
| 14 | 2018-08-08 | 2 |
| 15 | 2018-08-08 | 1 |
| 16 | 2018-08-08 | 1 |
+------+------------+------------+
select * from soldproduct;
+--------+-------------+----------+-------+------------+
| billid | productname | quantity | price | totalprice |
+--------+-------------+----------+-------+------------+
| 11 | book | 2 | 100 | 200 |
| 11 | pen | 10 | 10 | 100 |
| 11 | pencil | 5 | 2 | 10 |
| 12 | pencil | 5 | 2 | 10 |
| 13 | pen | 10 | 10 | 100 |
| 13 | book | 2 | 100 | 200 |
| 14 | pen | 1 | 10 | 10 |
| 14 | bottle | 1 | 75 | 75 |
| 15 | phone | 1 | 5000 | 5000 |
| 16 | lock | 15 | 50 | 750 |
+--------+-------------+----------+-------+------------+
I need to find the highest bill id using totalprice.
I tried using
select billid,sum(totalprice)
from soldproduct
where billid in (select id from bill where solddate >= date_sub(curdate(),interval 1 month))
group by billid
order by totalprice desc;
and my output is
+--------+-----------------+
| billid | sum(totalprice) |
+--------+-----------------+
| 15 | 5000 |
| 16 | 750 |
| 11 | 310 |
| 13 | 300 |
| 12 | 10 |
| 14 | 85 |
+--------+-----------------+
How do i get the same output with a single query using joins (without using subquery)?
try the following join
select billid,sum(totalprice)
from soldproduct
join bill on soldproduct.billid = bill.id and solddate >= date_sub(curdate(),interval 1
month)
group by billid
order by totalprice desc;
Can you try the below query:(I do not tested it out)
SELECT billid, SUM(totalprice)
FROM soldproduct SP
JOIN bill B ON (B.id = SP.billid)
WHERE B.solddate BETWEEN (CURRENT_DATE() - INTERVAL 1 MONTH) AND CURRENT_DATE()
GROUP BY SP.billid
ORDER BY SP.totalprice DESC;

Mysql query to select count a column distinct?

I using MySql and I have...
orders
+--------+---------+-------------+
| ID | PRO_ID | CUS_ID |
+--------+---------+-------------+
| 1 | 1 | 2 |
| 2 | 1 | 79 |
| 3 | 1 | 6 |
| 4 | 2 | 41 |
| 5 | 2 | 28 |
| 6 | 2 | 33 |
| 7 | 3 | 2 |
| 8 | 4 | 9 |
| 9 | 4 | 23 |
| 10 | 5 | 43 |
| 11 | 5 | 45 |
| 12 | 5 | 78 |
| 13 | 5 | 67 |
| 14 | 6 | 12 |
| 15 | 6 | 95 |
How to get 5 top PRO_ID and their count. Example
+---------+-------------+
| PRO_ID | COUNT |
+---------+-------------+
| 5 | 4 |
| 1 | 3 |
| 2 | 3 |
| 4 | 2 |
| 6 | 2 |
my orders table have 2 millions rows, i need a query faster. Thanks for any help!
Apply indexing for that particular field and go on with this query....i hope it will give you better performance
select PRO_ID,count(PRO_ID) as prod_count
from orders
group by PRO_ID
order by prod_count desc
limit 5
You can do like:
select PRO_ID, COUNT(*) as total
from test
group by PRO_ID
ORDER BY total desc, PRO_ID
limit 5
here is fiddle
select PRO_ID,count(PRO_ID) as count
from orders
group by PRO_ID
order by count desc
limit 5
If the query seems to slow then try adding index on your table

how to decide the Order of records as a Result of join query

The tables (from http://www.tutorialspoint.com/sql/sql-using-joins.htm)
1)Customers table:
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
| 7 | Muffy | 24 | Indore | 10000.00 |
+----+----------+-----+-----------+----------+
2) Orders table :
+-----+---------------------+-------------+--------+
|OID | DATE | CUSTOMER_ID | AMOUNT |
+-----+---------------------+-------------+--------+
| 102 | 2009-10-08 00:00:00 | 3 | 3000 |
| 100 | 2009-10-08 00:00:00 | 3 | 1500 |
| 101 | 2009-11-20 00:00:00 | 2 | 1560 |
| 103 | 2008-05-20 00:00:00 | 4 | 2060 |
+-----+---------------------+-------------+--------+
the inner join query is :
SELECT ID, NAME, AGE, AMOUNT
FROM CUSTOMERS, ORDERS
WHERE CUSTOMERS.ID = ORDERS.CUSTOMER_ID;
The result shown is :
+----+----------+-----+--------+
| ID | NAME | AGE | AMOUNT |
+----+----------+-----+--------+
| 3 | kaushik | 23 | 3000 |
| 3 | kaushik | 23 | 1500 |
| 2 | Khilan | 25 | 1560 |
| 4 | Chaitali | 25 | 2060 |
+----+----------+-----+--------+
My question : the resultant table is clearly ordered according to the "ORDERS" table i.e the oredering in ID column in result table is 3,3,2,4 acc. to ORDERS table. Why is the ordering of IDs not according to the CUSTOMERS table i.e why is the result not
ID
2
3
3
4
and the corresponding values .Is there some sort of rule for that ?
You should use order by like below
SELECT ID, NAME, AGE, AMOUNT
FROM CUSTOMERS, ORDERS
WHERE CUSTOMERS.ID = ORDERS.CUSTOMER_ID order by ID asc;
The order of a query result is not defined until you define it. Use an ORDER BY clause when you are interested in a particular order.
That being said...
Don't use old style joins anymore. Every RDBMS supports SQL-92 join syntax.
Get into the habit of prefixing columns with the table name. Use a table alias to save typing.
.
SELECT
c.ID, c.NAME, c.AGE, o.AMOUNT
FROM
CUSTOMERS c
INNER JOIN ORDERS o ON c.ID = o.CUSTOMER_ID
ORDER BY
c.ID;