mysql compare tables - mysql

I'm stuck with some tables in mysql. Don't really know how to join the info from three tables. Very thankful if anyone could help me. Thanks.
This is what I have:
Table1.Users
+----+--------+--------------+
| id | name | lastname |
+----+--------+--------------+
| 1 | Peter | Elk |
| 2 | Amy | Lee |
| 3 | James | Ride |
| 4 | Andrea | Thompson |
+----+--------+--------------+
Table2.Projects
+-----+-------------+
| id | name |
+-----+-------------+
| 13 | Lmental |
| 26 | Comunica |
| 28 | Ecobalear |
| 49 | Puigpunyent |
+-----+-------------+
Table3.Users_Projects
+----------+-------------+
| id_users | id_projects |
+----------+-------------+
| 1 | 13 |
| 1 | 28 |
| 2 | 13 |
| 2 | 28 |
| 2 | 49 |
| 3 | 28 |
| 3 | 49 |
| 4 | 49 |
+----------+-------------+
And I would like to print something like this:
+--------+--------------+----------------------------------+
| name | lastname | project |
+--------+--------------+----------------------------------+
| Peter | Elk | Lmental,Ecobalear |
| Amy | Lee | Lmental,Ecobalear, Puigpunyent |
| James | Ride | Ecobalear,Puigounyent |
| Andrea | Thompson | Puigpunyent |
+--------+--------------+----------------------------------+

Something like...
SELECT Users.name, Users.lastname, Projects.name
FROM (Users, Projects, Users_Projects)
WHERE Users_Projects.id_users=Users.id AND Users_Projects.id_projects=Projects.id
ORDER BY ...
...will output a single user/project per line, which you'll then have to manipulate in your choosen language.
Attempting to perform the concatenation, etc. in SQL is liable to lead to a pretty horrendous query.

Related

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 |
+----+-----------+---------+------------+------+

How to showing Group in Table ( Angular 6 above)

I want to ask, if I have a flat sales data in Json format :
[ {Amir,Adidas,36,2},{Amir,Nike,30,2},{Amir,Puma,37,3},
{{Meta,Adidas,41,1},{Meta,Nike,33,2},Meta, Puma,42,4},{Meta, Puma,43,3}
{Samsi,Adidas,40,1},Samsi,Nike,31,1},{Bulma,Puma,41,3} ]
and the data already sorted by Sales Name, Product Name, shoes no, and Name.
+---------------------+--------------+--------------+-------------------+
| Nama | Adidas | Nike | Puma |
| +----+----+----+----+----+----+----+----+----+----+
| | 36 | 40 | 41 | 30 | 31 | 33 | 37 | 41 | 42 | 43 |
+---------------------+----+----+----+----+----+----+----+----+----+----+
| Amir | 2 | | | 2 | | | 3 | | | |
| Meta | | | 1 | | | 2 | | | 4 | 3 |
| Samsi | | 1 | | | 1 | | | 3 | | |
+---------------------+----+----+----+----+----+----+----+--- +----+----+
How to make HTML table to present the data, like above.
I am using angular 6 as front end.
Thank You

Mysql table records are displayed in a crooked manner

I have created a table in MySQL but when I display the table, some records are displayed in a crooked manner.
Here's the table displayed:
select * from air_passenger_profile;
+------------+----------+------------+-----------+---------------------------------+---------------+---------------------+
| profile_id | password | first_name | last_name | address | mobile_number | email_id |
+------------+----------+------------+-----------+---------------------------------+---------------+---------------------+
| PFL001 | PFL001 | LATHA | SANKAR | 123 BROAD CROSS ST,CHENNAI-48 | 9876543210 | LATHA#GMAIL.COM |
| PFL002 | PFL002 | ARUN | PRAKASH | 768 2ND STREET,BENGALURU-20 | 8094564243 | ARUN#AOL.COM |
| PFL003 | PFL003 | AMIT | VIKARAM | 43 5TH STREET,KOCHI-84 | 9497996990 | AMIT#AOL.COM |
| PFL004 | PFL004 | AARTHI | RAMESH | 343 6TH STREET,HYDERABAD-76 | 9595652530 | AARTHI#GMAIL.COM |
| PFL005 | PFL005 | SIVA | KUMAR | 125 8TH STREET,CHENNAI-46 | 9884416986 | SIVA#GMAIL.COM |
| PFL006 | PFL006 | RAMESH | BABU | 109 2ND CROSS ST,KOCHI-12 | 9432198760 | RAMESH#GMAIL.COM |
| PFL007 | PFL007 | GAYATHRI | RAGHU | 23 2ND CROSS ST,BENGALURU-12 | 8073245678 | GAYATHRI#GMAIL.COM |
| PFL008 | PFL008 | GANESH | KANNAN | 45 3RD ST,HYDERABAD-21 | 9375237890 | GANESH#GMAIL.COM |
+------------+----------+------------+-----------+---------------------------------+---------------+---------------------+
You place it into your database with spaces. At the point where you insert your variables into the databse, you could use PHP's trim() function, or MySQL's, to store it without the spaces.
To correct your current values:
UPDATE air_passenger_profile SET first_name = TRIM(first_name), etc...

Group_Concat() is not working properly in mysql

I have three tables :
em_employee :
emp_number | emp_firstname |
+------------+---------------+
| 1 | Vikram |
| 2 | S. |
| 3 | Gopal |
| 4 | Vaishnavi |
| 5 | Srinivasan |
| 6 | Saravanan
em_project
+------------+------------------------------+
| project_id | name |
+------------+------------------------------+
| 339 | MoneyGram |
| 340 | SERVICE LINE HEAD COMPLIANCE |
| 341 | SERVICE LINE HEAD ANALYTICS |
| 342 | GSI |
| 343 | Tandem |
| 344 | Master Card |
+------------+------------------------------+
em_project_employee:
+------------+------------+
| emp_number | project_id |
+------------+------------+
| 1 | 339 |
| 2 | 340 |
| 3 | 341 |
| 4 | 342 |
| 1 | 343 |
| 6 | 344 |
| 2 | 342 |
+------------+------------+
And I want Output like :
+------------+----------------------------------+
| emp_number | name |
+------------+----------------------------------+
| 1 | MoneyGram , Tandem |
| 2 | SERVICE LINE HEAD COMPLIANCE,GSI |
| 3 | SERVICE LINE HEAD ANALYTICS |
| 4 | GSI |
| 6 | Master Card |
+------------+----------------------------------+
I have tried it with GROUP_CONCAT, but something going wrong. Please help me on this.
Try this query, it produes that output:
SELECT emp_number, GROUP_CONCAT(name) FROM em_project p
INNER JOIN em_project_employee em ON p.project_id = em.project_id
GROUP BY emp_number;
The order of the data will e slightly different from what's in your desired output. If the ordering is important.
GROUP_CONCAT(name ORDER BY p.project_id)

MySQL query is returning duplicates when it shouldn't

I have three tables:
Person
+--------+-----------+
| fName | lName |
+--------+-----------+
| Paul | McCartney |
| John | Lennon |
| Jon | Stewart |
| Daniel | Tosh |
| Steven | Colbert |
| Pink | Floyd |
| The | Beatles |
| Arcade | Fire |
| First | Last |
| Andrew | Bird |
+--------+-----------+
Publication
+----+---------------------------------------+------+-----------+---------+
| id | title | year | pageStart | pageEnd |
+----+---------------------------------------+------+-----------+---------+
| 9 | The Dark Side of the Moon | 1973 | 0 | 0 |
| 10 | Piper At The Gates of Dawn | 1967 | 0 | 0 |
| 11 | Sgt. Pepper's Lonely Hearts Band Club | 1967 | 0 | 0 |
| 12 | Happy Thoughts | 2007 | 0 | 60 |
| 13 | Wish You Were Here | 1975 | 0 | 0 |
| 14 | Funeral | 2004 | 0 | 0 |
+----+---------------------------------------+------+-----------+---------+
Person_Publication
+-----------+----------------+--------+---------------+
| person_id | publication_id | editor | author_number |
+-----------+----------------+--------+---------------+
| 11 | 11 | 0 | 1 |
| 12 | 11 | 0 | 1 |
| 16 | 9 | 0 | 1 |
| 17 | 11 | 0 | 1 |
+-----------+----------------+--------+---------------+
I'm trying to select all authors of a certain publication using the following query:
SELECT fName , lName
FROM Publication , Person, Person_Publication
WHERE Person.id = Person_Publication.person_id
AND Person_Publication.publication_id = 11;
But the results I get are always duplicates (always 6x for some reason). The results:
+-------+-----------+
| fName | lName |
+-------+-----------+
| Paul | McCartney |
| John | Lennon |
| The | Beatles |
| Paul | McCartney |
| John | Lennon |
| The | Beatles |
| Paul | McCartney |
| John | Lennon |
| The | Beatles |
| Paul | McCartney |
| John | Lennon |
| The | Beatles |
| Paul | McCartney |
| John | Lennon |
| The | Beatles |
| Paul | McCartney |
| John | Lennon |
| The | Beatles |
+-------+-----------+
18 rows in set (0.03 sec)
Can somebody please tell me why this is happening and how to fix this?
You are getting 6x your results, exactly one for each Publication row.
Remove your Publication from your FROM clause:
SELECT fName , lName
FROM Person, Person_Publication
WHERE Person.id = Person_Publication.person_id
AND Person_Publication.publication_id = 11;
You are including three tables in your query:
FROM Publication, Person, Person_Publication
but you have only one join condition:
WHERE Person.id = Person_Publication.person_id
You end up with a cartesian product between Publication and Person JOIN Person_Publication
Add the following condition to your WHERE block:
AND Publication.id = Person_Publication.publication.id
A perfect example of why the explicit JOIN syntax is prefered. With the following syntax:
SELECT fName, lName
FROM Publication
JOIN Person_Publication ON Person_Publication.publication.id = Publication.id
JOIN Person ON Person.id = Person_Publication.person_id
WHERE Person_Publication.publication_id = 11;
.. such a mistake simply cannot happen.