Retrieving max values for two related tables through SQL join table - mysql

I am trying to use an inner join to retrieve the best ratings for certain categories with the following SQL statement:
select expertise.category, sk.type from expertise inner join
(select skills.expertise_uuid, skills.type, max(skills.rating) as rating
from skills grouped by skills.expertise_uuid) as sk
on sk.expertise_uuid = expertise.uuid);
I have the following two tables:
mysql> select * from expertise;
+--------------------------------------+-----------------------+----------+--------------------------------------+
| uuid | category | favorite | user_profile_uuid |
+--------------------------------------+-----------------------+----------+--------------------------------------+
| 2a325545-5713-4b56-b3a1-9655875e2da7 | Frameworks & Tools | 0 | 32251c91-aff3-4aa0-8350-8a556db9bcd5 |
| 6166a5c4-2b64-4658-896a-c99fc79fa7ce | Programming languages | 1 | 32251c91-aff3-4aa0-8350-8a556db9bcd5 |
| 91d8b6da-57f5-49ee-83fc-37b8ac430e49 | Databases | 0 | 32251c91-aff3-4aa0-8350-8a556db9bcd5 |
| b452ffc0-a920-4b5c-8e96-947e5c7e1a31 | OS & Software | 0 | 32251c91-aff3-4aa0-8350-8a556db9bcd5 |
| c338733f-3a58-4e90-978c-1977abf6001c | Application servers | 0 | 32251c91-aff3-4aa0-8350-8a556db9bcd5 |
| e0149f2b-5bb4-4f27-aa37-58b228409bec | Languages | 0 | 32251c91-aff3-4aa0-8350-8a556db9bcd5 |
| eac89c26-f204-4b25-9b7e-3cb66cc75962 | Test | 0 | 32251c91-aff3-4aa0-8350-8a556db9bcd5 |
+--------------------------------------+-----------------------+----------+--------------------------------------+
7 rows in set (0.00 sec)
mysql> select * from skills;
+--------------------------------------+--------+-------+------------+--------------------------------------+
| uuid | rating | scale | type | expertise_uuid |
+--------------------------------------+--------+-------+------------+--------------------------------------+
| 130580c4-9359-4486-9c73-1f6daeac183a | 6 | 10 | Linux | b452ffc0-a920-4b5c-8e96-947e5c7e1a31 |
| 17842ee5-c0c3-412f-8b6a-eff8a9f72f95 | 3 | 10 | C++ | 6166a5c4-2b64-4658-896a-c99fc79fa7ce |
| 1967f7ab-e039-466c-af4d-deaa1b2dc5fe | 6 | 10 | Subversion | 2a325545-5713-4b56-b3a1-9655875e2da7 |
| 1bac44e7-75c5-45a9-b11d-fa74727e68a4 | 7 | 10 | MySQL | 91d8b6da-57f5-49ee-83fc-37b8ac430e49 |
| 1f2bc3e9-83f8-44a7-aa6a-65bb7eebb279 | 6 | 10 | Android | 6166a5c4-2b64-4658-896a-c99fc79fa7ce |
| 26e542fb-5a3a-46fd-847f-d69cc09608fb | 8 | 10 | Java | 6166a5c4-2b64-4658-896a-c99fc79fa7ce |
| 28572313-a9f8-41d1-8a62-a2535df23787 | 5 | 10 | WebSphere | c338733f-3a58-4e90-978c-1977abf6001c |
| 55f30986-4b61-4347-aaca-2346799ccd42 | 10 | 10 | Slovene | e0149f2b-5bb4-4f27-aa37-58b228409bec |
| 5dad7632-6bbf-4b70-801b-d24e2f24560e | 7 | 10 | Eclipse | b452ffc0-a920-4b5c-8e96-947e5c7e1a31 |
| 676dc2b0-de01-47ef-8c10-be81a57d3a57 | 6 | 10 | JavaScript | 6166a5c4-2b64-4658-896a-c99fc79fa7ce |
| 8db56cf5-e00a-4652-8f08-39a6ba9961ed | 3 | 10 | Drinking | NULL |
| a184ee09-05ab-4228-ba5d-0019d578367d | 7 | 10 | Git | 2a325545-5713-4b56-b3a1-9655875e2da7 |
| a22331ed-ce03-4dd9-a541-23cdccb0bde3 | 8 | 10 | Windows | b452ffc0-a920-4b5c-8e96-947e5c7e1a31 |
| b32c8898-117f-4685-b988-0d6012d2fdaa | 2 | 10 | C# | 6166a5c4-2b64-4658-896a-c99fc79fa7ce |
| b93c9c13-68c3-4f95-88e0-3ae3609b36be | 8 | 10 | IntelliJ | b452ffc0-a920-4b5c-8e96-947e5c7e1a31 |
| be2a85aa-a093-441c-adf5-3c9415d6112f | 7 | 10 | MacOS | b452ffc0-a920-4b5c-8e96-947e5c7e1a31 |
| d5844c34-fa9a-45cc-913d-9fb82d408d7f | 7 | 10 | English | e0149f2b-5bb4-4f27-aa37-58b228409bec |
| d72e50c4-0fbc-415b-970e-d33c8386174d | 2 | 10 | Scala | 6166a5c4-2b64-4658-896a-c99fc79fa7ce |
| dfefcc91-194e-4b54-ab07-51e186f60c18 | 5 | 10 | PHP | 6166a5c4-2b64-4658-896a-c99fc79fa7ce |
| ee2d4b52-0b22-4d1c-a0b1-27a0d23ccbca | 6 | 10 | Oracle | 91d8b6da-57f5-49ee-83fc-37b8ac430e49 |
| fd936710-edff-4cdb-8924-ff513f0d2315 | 7 | 10 | Jetty | c338733f-3a58-4e90-978c-1977abf6001c |
+--------------------------------------+--------+-------+------------+--------------------------------------+
21 rows in set (0.00 sec)
How would I be able to retrieve the category from expertise and the corresponding type in skills for the highest rated skills (rating column)? The result should look like this:
+-----------------------+--------+--------+
| category | rating | type |
+-----------------------+--------+--------+
| Frameworks & Tools | 7 | Git |
| Programming languages | 8 | Java |
| Databases | 7 | MySQL |
| OS & Software | 8 | Eclipse|
| Application servers | 7 | Jetty |
| Languages | 10 | Slovene|
+-----------------------+--------+--------+
I looked up several stack overflow questions, but I did not find any answer that could be used in this example.

If I understand correctly, you can use row_number():
select es.*
from (select e.category, s.rating, s.type,
row_number() over (partition by e.category order by s.rating desc) as seqnum
from expertise e join
skills s
on e.uuid = s.expertise_uuid
) es
where seqnum = 1;

I finally found another solution with two joins. I finally understood I can first look up all rows with highest ratings per expertise:
mysql> select skills.uuid, s.maxrating, skills.type, skills.expertise_uuid
from skills inner join
(select expertise_uuid, max(rating) as maxrating from skills
group by expertise_uuid) as s
on skills.expertise_uuid = s.expertise_uuid and skills.rating = s.maxrating;
+--------------------------------------+-----------+----------+--------------------------------------+
| uuid | maxrating | type | expertise_uuid |
+--------------------------------------+-----------+----------+--------------------------------------+
| 1bac44e7-75c5-45a9-b11d-fa74727e68a4 | 7 | MySQL | 91d8b6da-57f5-49ee-83fc-37b8ac430e49 |
| 26e542fb-5a3a-46fd-847f-d69cc09608fb | 8 | Java | 6166a5c4-2b64-4658-896a-c99fc79fa7ce |
| 55f30986-4b61-4347-aaca-2346799ccd42 | 10 | Slovene | e0149f2b-5bb4-4f27-aa37-58b228409bec |
| a184ee09-05ab-4228-ba5d-0019d578367d | 7 | Git | 2a325545-5713-4b56-b3a1-9655875e2da7 |
| a22331ed-ce03-4dd9-a541-23cdccb0bde3 | 8 | Windows | b452ffc0-a920-4b5c-8e96-947e5c7e1a31 |
| b93c9c13-68c3-4f95-88e0-3ae3609b36be | 8 | IntelliJ | b452ffc0-a920-4b5c-8e96-947e5c7e1a31 |
| fd936710-edff-4cdb-8924-ff513f0d2315 | 7 | Jetty | c338733f-3a58-4e90-978c-1977abf6001c |
+--------------------------------------+-----------+----------+--------------------------------------+
7 rows in set (0.00 sec)
Once I have this, I can use it to join results with expertise table.
mysql> select expertise.category, s2.type, s2.maxrating from expertise
inner join
(select skills.uuid, s.maxrating, skills.type, skills.expertise_uuid
from skills inner join
(select expertise_uuid, max(rating) as maxrating from skills
group by expertise_uuid) as s
on skills.expertise_uuid = s.expertise_uuid and skills.rating = s.maxrating)
as s2 on expertise.uuid = s2.expertise_uuid;
+-----------------------+----------+-----------+
| category | type | maxrating |
+-----------------------+----------+-----------+
| Databases | MySQL | 7 |
| Programming languages | Java | 8 |
| Languages | Slovene | 10 |
| Frameworks & Tools | Git | 7 |
| OS & Software | Windows | 8 |
| OS & Software | IntelliJ | 8 |
| Application servers | Jetty | 7 |
+-----------------------+----------+-----------+
7 rows in set (0.00 sec)

Related

select and group by same value mysql

i have table with data like this below
| id | wallet_id | wallet_name | deposit | |
|----|-----------|-------------|---------|---|
| 1 | 12 | a_wallet | 10 | |
| 2 | 14 | c_wallet | 12 | |
| 3 | 12 | a_wallet | 24 | |
| 4 | 15 | e_wallet | 50 | |
| 5 | 14 | c_wallet | 10 | |
| 6 | 15 | e_wallet | 22 | |
i want to select and group with same wallet_id, probably something like this
| wallet_id | id | wallet_name |
|-----------|----|-------------|
| 12 | 1 | a_wallet |
| | 3 | a_wallet |
| 14 | 2 | c_wallet |
| | 5 | c_wallet |
| 15 | 4 | e_wallet |
| | 6 | e_wallet |
i already try
select wallet_id, id, wallet_name from wallet group by wallet_id
but it shows like usual select query with no grouping.
Kindly need your help, thanks
We would generally handle your requirement from the presentation layer (e.g. PHP), but if you happen to be using MySQL 8+, here is a way to do this directly from MySQL:
SELECT
CASE WHEN ROW_NUMBER() OVER (PARTITION BY wallet_id ORDER BY id) = 1
THEN wallet_id END AS wallet_id,
id,
wallet_name
FROM wallet w
ORDER BY w.wallet_id, id;

Compare number of credits users using two different tables in MySql 8

On my MySql version 8.0.17 database I have two different tables.
In the table table_credits_used I stored for each user the number of access in shared area for current date.
mysql> SELECT
COUNT(*) tCount,
tNameUser
FROM
`table_credits_used`
WHERE
tDate = CURDATE()
GROUP BY
tDate,
tNameUser;
+--------+-----------+
| tCount | tNameUser |
+--------+-----------+
| 1 | Chenoa |
| 6 | Kimi |
| 1 | Aponi |
| 1 | Imala |
| 6 | Doba |
| 1 | Elsu |
| 1 | Jair |
| 2 | Nova |
| 1 | Aarav |
| 1 | Aarush |
| 1 | Aaryan |
| 1 | Aayansh |
| 1 | Aayush |
| 5 | Abeer |
| 1 | Adhrit |
| 2 | Adi |
| 1 | Aditya |
| 1 | Advaith |
| 6 | Advay |
| 6 | Advik |
| 6 | Agastya |
+--------+-----------+
21 rows in set (0.04 sec)
In the table table_credit_to_use is stored for each user the maximum number of access in shared area for current date.
mysql> SELECT * FROM `table_credit_to_use`;
+--------+-----------+-----+
| tCount | tNameUser | tID |
+--------+-----------+-----+
| 1 | Chenoa | 1 |
| 6 | Kimi | 2 |
| 1 | Aponi | 3 |
| 1 | Imala | 4 |
| 6 | Doba | 5 |
| 1 | Elsu | 6 |
| 1 | Jair | 7 |
| 2 | Nova | 8 |
| 1 | Aarav | 9 |
| 1 | Aarush | 10 |
| 1 | Aaryan | 11 |
| 1 | Aayansh | 12 |
| 1 | Aayush | 13 |
| 6 | Abeer | 14 |
| 1 | Adhrit | 15 |
| 2 | Adi | 16 |
| 1 | Aditya | 17 |
| 1 | Advaith | 18 |
| 6 | Advay | 19 |
| 6 | Advik | 20 |
| 6 | Agastya | 21 |
+--------+-----------+-----+
21 rows in set (0.04 sec)
I need to show users who have not consumed the maximum number of logins for the current date.
In this example, I need this output:
+--------+-----------+-----+
| tCount | tNameUser | tID |
+--------+-----------+-----+
| 5 | Abeer | 14 |
+--------+-----------+-----+
Because the user Abeer has the right to 6 total accesses, but today he has used only 5.
Any suggestion?
My table structure below on db-fiddle.com, which offers MySQL 8.0
Make sure you have you have ONLY_FULL_GROUP_BY disabled in MySQL.
mysql> SET GLOBAL sql_mode=(SELECT REPLACE(##sql_mode,'ONLY_FULL_GROUP_BY',''));
The following SQL should do the trick:
SELECT cu.tCount, cu.tNameUser, cu.tID FROM table_credits_used cu
INNER JOIN table_credit_to_use ctu ON (ctu.tID = cu.tID)
WHERE cu.tCount < ctu.tCount
AND cu.tDate = CURDATE()
GROUP BY cu.tDate, cu.tNameUser;
Note: The ONLY_FULL_GROUP_BY is enabled on the dbfiddle hence I couldn't try the above full query. The one that worked in db fiddle is the following without the group by clause:
SELECT cu.tCount, cu.tNameUser, cu.tID FROM table_credits_used cu
INNER JOIN table_credit_to_use ctu ON (ctu.tID = cu.tID)
WHERE cu.tCount < ctu.tCount;
Your sample data has no tdate
But you can join the table with the subselect
SELECT
t1.tNameUser,t1.tCount,t2.tCount current_count
FROM `table_credit_to_use` t1
INNER JOIN ( SELECT
COUNT(*) tCount,
tNameUser
FROM
`table_credits_used`
WHERE
tDate = CURDATE()
GROUP BY
tDate,
tNameUser) t2 ON t1.tNameUser = t2.tNameUser

Issue concatenating rows with duplicates

I have run into some issues trying to combine a row of variables where dublicates can be found.
Computers with Ids are saved in the Computer table:
| Computer.Id |
|-------------|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
Harddrive are saved in a HardDisk table with a HardDisk Id exclusive to the harddrive and a ComputerId linked to the Id in the Computer table
| Harddisk.ComputerId | Harddisk.Id |
|---------------------|-------------|
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 6 | 7 |
| 7 | 8 |
| 8 | 9 |
| 9 | 10 |
The output I am looking to achieve is:
| Harddisk.ComputerId | Harddisk.Id |
|---------------------|-------------|
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6,7 |
| 7 | 8 |
| 8 | 9 |
| 9 | 10 |
The output I'm currently getting is:
| Harddisk.ComputerId | Harddisk.Id |
|---------------------|-------------|
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 8 |
| 8 | 9 |
| 9 | 10 |
Notice how Harddisk 7 which is the disk that shares Computer 6 is gone.
My current query looks like the following, courtesy of scaisEdge:
SELECT *, group_concat(HardDisk.Id)
from Computer
inner join HardDisk on Computer.Id = HardDisk.ComputerId
group by Computer.Id
I hope someone is able to help me out!
You can't use * because this produce an a wrong aggregation in mysql for version < 5.7
try use explicit column's name in select
SELECT computer.ID, group_concat(HardDisk.Id) my_disk
from Computer
inner join HardDisk on Computer.Id = HardDisk.ComputerId
group by Computer.Id
if you need more column's not related to the same aggreagtion level you need a join
In mysql version < 5.7 if some columns mentioned in select clause are not mentioned properly in group by the aggregation function return the first occurrence of the select and not the correct aggreagted result
try add
echo $row['my_disk];

How to get count of combinations from database?

How to get count of combinations from database?
I have to database tables and want to get the count of combinations. Does anybody know how to put this in a database query, therefore I haven't a db request for each trip?
Trips
| ID | Driver | Date |
|----|--------|------------|
| 1 | A | 2015-12-15 |
| 2 | A | 2015-12-16 |
| 3 | B | 2015-12-17 |
| 4 | A | 2015-12-18 |
| 5 | A | 2015-12-19 |
Passengers
| ID | PassengerID | TripID |
|----|-------------|--------|
| 1 | B | 1 |
| 2 | C | 1 |
| 3 | D | 1 |
| 4 | B | 2 |
| 5 | D | 2 |
| 6 | A | 3 |
| 7 | B | 4 |
| 8 | D | 4 |
| 9 | B | 5 |
| 10 | C | 5 |
Expected result
| Driver | B-C-D | B-D | A | B-C |
|--------|-------|-----|---|-----|
| A | 1 | 2 | - | 1 |
| B | - | - | 1 | - |
Alternative
| Driver | Passengers | Count |
|--------|------------|-------|
| A | B-C-D | 1 |
| A | B-D | 2 |
| A | B-C | 1 |
| B | A | 1 |
Has anybody an idea?
Thanks a lot!
Try this:
SELECT Driver, Passengers, COUNT(*) AS `Count`
FROM (
SELECT t.ID, t.Driver,
GROUP_CONCAT(p.PassengerID
ORDER BY p.PassengerID
SEPARATOR '-') AS Passengers
FROM Trips AS t
INNER JOIN Passengers AS p ON t.ID = p.TripID
GROUP BY t.ID, t.Driver) AS t
GROUP BY Driver, Passengers
The above query will produce the alternative result set. The other result set can only be achieved using dynamic sql.
Demo here

Finding all parents in mysql table with single query (Recursive Query)

I have this schema
Sample Data
| ID | TITLE | CONTROLLER | METHOD | PARENT_ID |
|----|-------------------|------------|-------------------|-----------|
| 1 | Dashboard | admin | dashboard | 0 |
| 2 | Content | admin | content | 0 |
| 3 | Modules | admin | modules | 0 |
| 4 | Users | admin | users | 0 |
| 5 | Settings | admin | settings | 0 |
| 6 | Reports | admin | reports | 0 |
| 7 | Help | admin | help | 0 |
| 8 | Pages | content | pages | 2 |
| 9 | Media | content | media | 2 |
| 10 | Articles | content | articles | 2 |
| 11 | Menues | content | menues | 2 |
| 12 | Templates | content | templates | 2 |
| 13 | Themes | content | themes | 2 |
| 14 | Blog | content | blog | 2 |
| 15 | Forum | content | forum | 2 |
| 16 | Core Modules | modules | core_module | 3 |
| 17 | User Modules | modules | user_module | 3 |
| 18 | All Users | users | all_users | 4 |
| 19 | Groups | users | groups | 4 |
| 20 | Permissions | users | permissions | 4 |
| 21 | Import and Export | users | import_export | 4 |
| 22 | Send Email | users | send_mail | 4 |
| 23 | Login Records | users | login_records | 4 |
| 24 | General Settings | settings | general_settings | 5 |
| 25 | Email Settings | settings | email_settings | 5 |
| 26 | Popular Content | reports | popular_content | 6 |
| 27 | Most Active Users | reports | most_active_users | 6 |
| 28 | Documentation | help | documentation | 7 |
| 29 | About | help | about | 7 |
| 30 | Products | products | product | 17 |
| 31 | Categories | categories | category | 17 |
SQL Fiddle demo.I have inserted some sample data.
Challange
I need to find all the parents of the record where the title is Categories. How can I get all the parents with only a single query?
I mean I need this result:
Desired Output
id | title | controller | method | url | parent_id
----------------------------------------------------------------
3 | Modules | admin | modules | (NULL) | 0
17 | User Modules | modules | user_module | (NULL) | 3
31 | Categories | categories | category | (NULL) | 17
Let suppose I want to fetch an entry with all of its parent and I want to use the where condition id = 31, it should fetch above records.
SELECT T2.id, T2.title,T2.controller,T2.method,T2.url
FROM (
SELECT
#r AS _id,
(SELECT #r := parent_id FROM menu WHERE id = _id) AS parent_id,
#l := #l + 1 AS lvl
FROM
(SELECT #r := 31, #l := 0) vars,
menu m
WHERE #r <> 0) T1
JOIN menu T2
ON T1._id = T2.id
ORDER BY T1.lvl DESC;
Demo