Display duplicate column with increasing count in separate column in sql - mysql

I want to increase count in count column one by one if the same Id is found in records.
Don't consider about auto increment of Id.
MySQL version 8.0 and you can order by name column.
I tried but not getting any solution.
My table Employee looks like this
+------+-------+-------+
| Id | Name |address|
+------+-------+-------+
| 111 | Sam | xyz |
| 112 | Mike | xyz |
| 113 | Carol | xyz |
| 113 | Bob | xyz |
| 113 | John | xyz |
| 116 | Adam | xyz |
| 116 | David | xyz |
+------+-------+-------+
I want to run sql query which will give output like this, if Id is same increase count
+------+-------+-------+
| Id | Name | count |
+------+-------+-------+
| 111 | Sam | 1 |
| 112 | Mike | 1 |
| 113 | Carol | 1 |
| 113 | Bob | 2 |
| 113 | John | 3 |
| 114 | Adam | 1 |
| 114 | David | 2 |
+------+-------+-------+

The ROW_NUMBER() function can generate your current count column, more or less:
SELECT
Id,
Name,
ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Name) count
FROM yourTable
ORDER BY
Id,
Name;
Note that ROW_NUMBER requires MySQL 8+.

Related

How to combine datas with same column and ignore null values in mysql

I'm just going to ask how to query combine datas with same column and ignore all null values
actual table:
id | first_name | last name | age | unique_id
1 | Doe | | | 111
2 | | John | | 111
3 | | | 32 | 111
4 | Reeves | | | 222
5 | | Keanu | | 222
wanted query result :
first_name | last name | age | unique_id
Doe | John | 32 | 111
Keanu | Reeves | | 222
Thanks!!
Aggregate by unique_id and use MAX:
SELECT
unique_id,
MAX(first_name) AS first_name,
MAX(last_name) AS last_name,
MAX(age) AS age
FROM yourTable
GROUP BY
unique_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 ;

How to get only the second duplicated record in laravel 5.5?

Let's say i have a user table like this :
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 1 | John | john.doe1#mail.com | 24 |
| 2 | Josh | josh99#mail.com | 29 |
| 3 | Joseph | joseph410#mail.com | 21 |
| 4 | George | gge.48#mail.com | 28 |
| 5 | Joseph | jh.city89#mail.com | 24 |
| 6 | Kim | kimsd#mail.com | 32 |
| 7 | Bob | bob.s#mail.com | 38 |
| 8 | Joseph | psa.jos#mail.com | 34 |
| 9 | Joseph | joseph.la#mail.com | 28 |
| 10 | Jonathan | jonhan#mail.com | 22 |
+----+-----------+---------+------------+------+
In the actual, the database consists of more data and some of the data is duplicated, with more than two records. But the point is i want to get only the first and the second row of the duplicated rows that contains the name of "Joseph", How can i achieve this ? My code so far...
User::withTrashed()->groupBy('name')->havingRaw('count("name") >= 1')->get();
With that code the result will retrieve :
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 1 | John | john.doe1#mail.com | 24 |
| 2 | Josh | josh99#mail.com | 29 |
| 3 | Joseph | joseph410#mail.com | 21 |
| 4 | George | gge.48#mail.com | 28 |
| 6 | Kim | kimsd#mail.com | 32 |
| 7 | Bob | bob.s#mail.com | 38 |
| 10 | Jonathan | jonhan#mail.com | 22 |
+----+-----------+---------+------------+------+
And i use this code to try to get the second duplicated row :
User::withTrashed()->groupBy('name')->havingRaw('count("name") >= 2')->get();
The result is still same as the mentioned above :
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 1 | John | john.doe1#mail.com | 24 |
| 2 | Josh | josh99#mail.com | 29 |
| 3 | Joseph | joseph410#mail.com | 21 |
| 4 | George | gge.48#mail.com | 28 |
| 6 | Kim | kimsd#mail.com | 32 |
| 7 | Bob | bob.s#mail.com | 38 |
| 10 | Jonathan | jonhan#mail.com | 22 |
+----+-----------+---------+------------+------+
I want the result is to get record that have the id "5" with name "Joseph" like this :
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 1 | John | john.doe1#mail.com | 24 |
| 2 | Josh | josh99#mail.com | 29 |
| 4 | George | gge.48#mail.com | 28 |
| 5 | Joseph | jh.city89#mail.com | 24 |
| 6 | Kim | kimsd#mail.com | 32 |
| 7 | Bob | bob.s#mail.com | 38 |
| 10 | Jonathan | jonhan#mail.com | 22 |
+----+-----------+---------+------------+------+
But it seems only the first duplicate row is retrieved and i can't get the second duplicated row, can anybody give me suggestion ?
Let's start from your query
User::withTrashed()->groupBy('name')->havingRaw('count("name") >= 1')->get();
This will show all groups of rows whose count equals to 1 ore more. and this is the description of DISTINCT.
If you want to get only duplicate records you should get groups whose count is LARGER than 1.
The other thing to notice here is that a non-aggrigated column will be chosen randomly. because when you get a name and it's count, for example if you select name,count(name), email (email is not in the group by clause - not aggregated), and 4 rows have the same name. so you'll see:
+--------+-------------+-------+
| Name | Count(Name) | Email |
+--------+-------------+-------+
| Joseph | 4 | X |
+--------+-------------+-------+
what do you expect instead of X? which one of the 4 emails? actually, in SQLServer it's forbidden to select a non-aggrigated column and other databases will just give you a random one of the counted 3.
see this answer for more details it's explained very well: Do all columns in a SELECT list have to appear in a GROUP BY clause
So, we'll use having count(name) > 1 and select only the aggregated column name
DB::from('users')->select('name')->groupBy('name')->havingRaw('count("name") > 1')->get();
This should give you (didn't test it) this:
+--------+-------------+
| name | Count(name) |
+--------+-------------+
| Joseph | 4 |
+--------+-------------+
This will give you all names who have 2 or more instances. you can determine the number of duplicates in the having clause. for example having count(name) = 3 will give you all names which have exactly 3 duplicates.
So how to get the second duplicate? I have a question for that:
What is the first (original) duplicate? is it the one with the oldest created_at or the oldest updated_at ? or maybe some other condition?. because of that you should make another query with order by clause to give you the duplicates in the order most convenient to you. for example:
select * from `users` where `name` in (select `name` from users group by `name` having count(`name`) > 1) order by `id` asc
which will give:
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 3 | Joseph | joseph410#mail.com | 21 |
| 5 | Joseph | jh.city89#mail.com | 24 |
| 8 | Joseph | psa.jos#mail.com | 34 |
| 9 | Joseph | joseph.la#mail.com | 28 |
+----+-----------+---------+------------+------+

Getting required rows in mysql using GROUPBY

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

What is the correct way of getting data from a MySQL table based on columns from another? Transposing?

I have a table like this:
idstable
+--------+-----+-----+-----+-----+-----+
| userid | id1 | id2 | id3 | id4 | id5 |
+--------+-----+-----+-----+-----+-----+
| 1 | 6 | 2 | 52 | 32 | 16 |
+--------+-----+-----+-----+-----+-----+
| 2 | 12 | 5 | 18 | 21 | 5 |
+--------+-----+-----+-----+-----+-----+
| ... | ... | ... | ... | ... | ... |
which i want to get the id numbers stored in the columns and get rows from another table with them. The table i wish to get the rows from is:
namestable
+----+----------+
| id | name |
+----+----------+
| 6 | Bruce |
+----+----------+
| 2 | Mary |
+----+----------+
| 52 | Dick |
+----+----------+
| 32 | Bob |
+----+----------+
| 16 | Jack |
+----+----------+
| .. | ... |
The result-set i'm im trying to get is something like:
+------+----+-------+
| User | id | name |
+------+----+-------+
| 1 | 6 | Bruce |
+------+----+-------+
| 1 | 2 | Mary |
+------+----+-------+
| 1 | 52 | Dick |
+------+----+-------+
| 1 | 32 | Bob |
+------+----+-------+
| 1 | 16 | Jack |
+------+----+-------+
How can i query the idstable with a userid to retrieve the ids associated with it, to then retrieve the correct rows from the namestable? I've read this is called transposing but i've yet to find a concise example.
Any ideas?
join
SELECT idstable.id as User, namestable.id as id, namestable.name as name
FROM idstable it
JOIN namestable nt on (nt.id = it.id1 or nt.id = it.id2 ... 3,4,5 like the first two)
Ideally, your idstable wouldn't have 5 columns, but 5 rows per per id.