select data from multiple tables by matching multiple columns - mysql

I have 3 tables like so:
Table User
+---------+-----------------+
| UserId | UserName |
+---------+-----------------+
| 1 | one#test.com |
| 2 | two#test.com |
| 3 | three#test.com |
| 4 | four#test.com |
+---------+-----------------+
Table Employee
+-------------+----------------+------------+----------+---------+
| EmployeeId | Email | Department | Position | Duty |
+-------------+----------------+------------+----------+---------+
| 1 | one#test.com | Accounting | Manager | Aproval |
| 2 | two#test.com | Accounting | Manager | NULL |
| 3 | three#test.com | Marketing | Staff | NULL |
| 4 | four#test.com | Purchasing | Staff | NULL |
+-------------+----------------+------------+----------+---------+
Table Authorization
+------------------+----------------+------------+----------+----------+
| AuhtorizationId | Level | Department | Position | Duty |
+------------------+----------------+------------+----------+----------+
| 1 | 1 | Accounting | Manager | NULL |
| 2 | 2 | Marketing | Staff | NULL |
| 3 | 3 | Purchasing | Staff | NULL |
| 4 | 4 | Accounting | Manager | Approval |
+------------------+----------------+------------+----------+----------+
How to construct a MySQL query to retrieve UserId, UserName/Email, Level, Department, and Position?

If I understand correctrly all the table relations
SELECT UserID, UserName, Level, Department, Position FROM User
INNER JOIN Employee ON UserId=EmployeeID INNER JOIN Authorization ON UserId = AuhtorizationId

Query:
SQLFiddleExample
SELECT
u.`UserID`,
u.`UserName`,
a.`Level`,
e.`Department`,
e.`Position`
FROM `User` u
LEFT JOIN `Employee` e
ON u.`UserId` = EmployeeID
LEFT JOIN `Authorization` a
ON u.`UserId` = a.`AuhtorizationId`
Result:
| USERID | USERNAME | LEVEL | DEPARTMENT | POSITION |
-----------------------------------------------------------
| 1 | one#test.com | 1 | Accounting | Manager |
| 2 | two#test.com | 2 | Accounting | Manager |
| 3 | three#test.com | 3 | Marketing | Staff |
| 4 | four#test.com | 4 | Purchasing | Staff |

SELECT User.UserID, User.UserName, Authorization.Level, Authorization.Department, Authorization.Position FROM User INNER JOIN Employee ON User.UserId=Employee.EmployeeID INNER JOIN Authorization ON Employee.Department = Authorization.Department WHERE Employee.Position=Authorization.Position AND Employee.Duty=Authorization.Duty

Related

How to combine multiple rows into a column based on a condition in Mysql?

I have two tables as follows.
Category table
+------------+------------+--------------+
| CategoryID | Name | CategoryCode |
+------------+------------+--------------+
| 1 | Fixed | |
| 2 | Consumable | |
| 3 | Intangible | |
+------------+------------+--------------+
Type table
+--------+------------+-------------------------+----------+
| TypeID | CategoryID | Name | TypeCode |
+--------+------------+-------------------------+----------+
| 1 | 1 | Furniture | |
| 2 | 1 | Computers & Peripherals | |
| 3 | 2 | Keyboards | |
| 4 | 2 | Other | |
| 5 | 3 | Software | |
+--------+------------+-------------------------+----------+
The result I want is like this
+------------+------------+------------------------------------+
| CategoryID | Category | Types |
+------------+------------+------------------------------------+
| 1 | Fixed | Furniture, Computers & Peripherals |
| 2 | Consumable | Keyboards, other |
| 3 | Intangible | Software |
+------------+------------+------------------------------------+
Appriciate if you could help me with wirting the query in MySQL
You can try this solution
SELECT
a.CategoryId,
a.`Name` Category,
GROUP_CONCAT(b.`Name`) Types
FROM
Category a
INNER JOIN Type b ON b.CategoryID = a.CategoryId
GROUP BY a.CategoryId

Get the last booking by its status (mysql)

I currently have a table that contains reservations. Another table with different status assigned to a reservation. A reservation with several status to keep track of the different status.
I would like to retrieve all the bookings in relation to the LAST status of the reservation.
| | | | |
|-------------|------------|----------------|-----------------------|
| Booking | | | |
| id | name | | |
| 1 | aaa | | |
| 2 | bbb | | |
| 3 | ccc | | |
| | | | |
| Status | | | |
| id | booking_id | type_status_id | date_of_change_status |
| 1 | 1 | 1 | xxx-xx-xx 00:00:00 |
| 2 | 1 | 2 | xxx-xx-xx 00:00:00 |
| 3 | 2 | 1 | xxx-xx-xx 00:00:00 |
| 4 | 2 | 2 | xxx-xx-xx 00:00:00 |
| | | | |
| Type_status | | | |
| id | name | | |
| 1 | Started | | |
| 2 | Updated | | |
| 3 | Finished | | |
Here is the code that I have for the moment, it returns well to me the reservations which passed by the status but not like last status.
SELECT b.name, b.id, b.date_booking, b.price, b.reference FROM booking b
INNER JOIN (SELECT MAX(s.id), s.booking_id, s.type_status_id FROM status s
WHERE s.type_status_id = 5
GROUP BY booking_id) AS status_max
ON b.id = status_max.booking_id
Thanks
Calculate the "latest" date of status change in a subquery using MAX() then include that as a subquery in the joins to restrict which rows from the status table get returned.
select
*
from Booking b
inner join Status s on b.id = s.bookingid
inner join (
select booking_id, max(date_of_change_status) latest_status_date
from status
group by
) l on b.id = l.bookingid
and s.date_of_change_status = l.latest_status_date
inner join Type_status ts on s.type_status_id = ts.id

Select/Join multiple fields from different tables with same column name

I have one key table, a number of data tables with same column names in them, and one users table. I am trying to select values from the key table, join this output with some selected values from each of the data tables by unique ID (uaID) to the entries selected already from the key table (each key table result will have a relative join from only one of the range of data tables, not all of them and some entries will return a null result from the data tables and we don't want this to break anything or be omitted because of the null result), and then finally join some user data to each result from the users table. This will always have a result.
Let me "draw" a basic version of my tables so you can see.
keyTable
-----------------------------------------
| uaID | userID | key | appName |
|---------------------------------------|
| 1 | 7 | ABC01 | Physics |
| 2 | 9 | DEF20 | Geometry |
| 3 | 12 | XJG14 | Biology |
| 4 | 19 | DAF09 | Chemistry |
| 5 | 27 | KYT78 | Algebra |
| 6 | 29 | PLF43 | Statistics|
| 7 | 34 | COG89 | Geology |
| 8 | 45 | HYL72 | Art |
| 9 | 48 | TSK45 | History |
| 10 | 53 | BBS94 | GeoChem |
| 11 | 59 | DOD10 | BioChem |
| 12 | 27 | HKV62 | Music |
-----------------------------------------
dataTable01
-----------------------------------------------
| uaID | sector | subSector | topic |
|---------------------------------------------|
| 2 | circle | volumn | measure |
| 7 | triangle | hypotenuse |pythagoras |
| 8 | square | | |
| 11 | triangle | hypotenuse |pythagoras |
-----------------------------------------------
dataTable02
---------------------
| uaID | topic |
|-------------------|
| 1 | door |
| 3 | window |
| 9 | porch |
| 12 | |
---------------------
dataTable03
-----------------------------------------------
| uaID | sector | subSector | topic |
|---------------------------------------------|
| 4 | cat | feline | kitty |
| 5 | dog | canine | rover |
| 6 | kangaroo | marsupial | jack |
| 10 | bunny | leporidae | peter |
-----------------------------------------------
users
------------------------------------------------------------------------
| userID | Title | firstName | lastName | email |
|----------------------------------------------------------------------|
| 7 | Dr | Melissa | Smith | mel#email.com |
| 9 | Mr | Bob | Andrews | bob#email.com |
| 12 | Miss | Clare | Greco | clare#email.com |
| 19 | Mr | Dan | Fonseca | dan#email.com |
| 27 | Mr | Matt | Jones | matt#email.com |
| 29 | Mr | Chris | Nimmo | chris#email.com |
| 34 | Mrs | Lisa | Araujo | lisa#email.com |
| 45 | Miss | Raquel | Bailey | raquel#email.com |
| 48 | Dr | Steven | Dowd | steven#email.com |
| 53 | Prof | Roger | Hesp | roger#email.com |
| 59 | Prof | Sally | Bryce | sally#email.com |
| 65 | Mrs | Elena | Eraway | elena#email.com |
------------------------------------------------------------------------
And this is what I am trying to achieve as the end result:
-------------------------------------------------------------------------------------------------------------------------------
| uaID | key | appName | sector | subSector | topic | title | firstName | lastName | email |
|-----------------------------------------------------------------------------------------------------------------------------|
| 1 | ABC01 | Physics | | | door | Dr | Melissa | Smith | mel#email.com |
| 2 | DEF20 | Geometry | circle | volumn | measure | Mr | Bob | Andrews | bob#email.com |
| 3 | XJG14 | Biology | | | window | Miss | Clare | Greco | clare#email.com |
| 4 | DAF09 | Chemistry | cat | feline | kitty | Mr | Dan | Fonseca | dan#email.com |
| 5 | KYT78 | Algebra | dog | canine | rover | Mr | Matt | Jones | matt#email.com |
| 6 | PLF43 | Statistics| kangaroo | marsupial | jack | Mr | Chris | Nimmo | chris#email.com |
| 7 | COG89 | Geology | triangle | hypotenuse |pythagoras | Mrs | Lisa | Araujo | lisa#email.com |
| 8 | HYL72 | Art | square | | | Miss | Raquel | Bailey | raquel#email.com |
| 9 | TSK45 | History | | | porch | Dr | Steven | Dowd | steven#email.com |
| 10 | BBS94 | GeoChem | bunny | leporidae | peter | Prof | Roger | Hesp | roger#email.com |
| 11 | DOD10 | BioChem | triangle | hypotenuse |pythagoras | Prof | Sally | Bryce | sally#email.com |
| 12 | HKV62 | Music | | | | Mr | Matt | Jones | matt#email.com |
-------------------------------------------------------------------------------------------------------------------------------
I am attempting to achieve this by executing:
$sql = "SELECT keyTable.uaID, keyTable.userID, keyTable.key,
keyTable.appName, dataTable01.sector, dataTable01.subSector,
dataTable01.topic, dataTable02.topic, dataTable03.sector,
dataTable03.subSector, dataTable03.topic, users.title,
users.firstName, users.lastName, users.email
FROM keyTable
LEFT OUTER JOIN dataTable01 ON keyTable.uaID = dataTable01.uaID
LEFT OUTER JOIN dataTable02 ON keyTable.uaID = dataTable02.uaID
LEFT OUTER JOIN dataTable03 ON keyTable.uaID = dataTable03.uaID
LEFT OUTER JOIN users ON keyTable.userID = users.userID";
I get all the keyTable data. I get all the users data right where it's supposed to join up all ok. I get all the dataTable03 data as well, but I do not get any data from dataTable01 or dataTable02 showing up in the result. If I omit the call to dataTable03 I then get all the relevant data from dataTable02 showing up, but no data from dataTable01. The call to the users table is at the end and always shows up fine. So clearly it's an issue with the matching field names in the data tables. I get no errors at all and the process completes, just with the mentioned data missing. I've tried different JOINS - INNER JOIN, OUTER JOIN, LEFT OUTER JOIN. There obviously has to be a way to achieve this but cannot seem to find any references on the web to this specific problem. Can someone tell me what I am doing incorrectly please?
After joining, you can use COALESCE to get the non-null value from the table with a matching row.
$sql = "SELECT k.uaID, k.userID, k.key, k.appName,
COALESCE(d1.sector, d3.sector, '') AS sector,
COALESCE(d1.subSector, d3.subSector, '') AS subSector,
COALESCE(d1.topic, d2.topic, d3.topic, '') AS topic,
users.title, users.firstName, users.lastName, users.email
FROM keyTable AS k
LEFT OUTER JOIN dataTable01 AS d1 ON k.uaID = d1.uaID
LEFT OUTER JOIN dataTable02 AS d2 ON k.uaID = d2.uaID
LEFT OUTER JOIN dataTable03 AS d3 ON k.uaID = d3.uaID
LEFT OUTER JOIN users ON k.userID = users.userID
ORDER BY k.uaID";
Another way to merge the data from the datatablesNN tables into the same column os tp use UNION.
SELECT k.uaID, k.userID, k.key, k.appName, IFNULL(d.sector, '') AS sector, IFNULL(d.subSector, '') AS subSector, IFNULL(d.topic, '') AS topic,
u.title, u.firstName, u.lastName, u.email
FROM keyTable AS k
LEFT OUTER JOIN (
SELECT uaID, sector, subSector, topic
FROM dataTable01
UNION
SELECT uaID, NULL, NULL, topic
FROM datatable02
UNION
SELECT uaID, sector, subSector, topic
FROM datatable03) AS d
ON k.uaID = d.uaID
LEFT JOIN users AS u ON u.userID = k.userID
ORDER BY k.uaID
DEMO
You would have to use aliases
simular issue and solution here:
php-mysql-how-to-resolve-ambiguous-column-names-in-join-operation
select * from common inner join (
(select link from table1)
union
(select link from table2)
) as unionT
on unionT.link = common.link

mySQL Table Join - Wrong Answer

I'm quite new to mySQL queries and struggling to achieve the result I require.
I have two tables of user information that I need to present. The tables are as follows:
users
+----+------------------+
| id | email |
+----+------------------+
| 1 | joe#hotmail.com |
| 2 | john#hotmail.com |
| 3 | fred#hatmail.com |
+----+------------------+
user_detail
+----------+--------+--------+
| detailid | userid | detail |
+----------+--------+--------+
| 1 | 1 | Joe |
| 2 | 1 | Soap |
| 1 | 2 | John |
| 2 | 2 | Doe |
| 1 | 3 | Fred |
| 2 | 3 | Bloggs |
+----------+--------+--------+
I have constructed the following query which joins the tables:
SELECT id, detail , email
FROM users
LEFT JOIN user_detail
ON users.id=user_detail.userid
ORDER by id
The query produces this result:
+--------+--------+------------------+
| userid | detail | email |
+--------+--------+------------------+
| 1 | Joe | joe#hotmail.com |
| 1 | Soap | joe#hotmail.com |
| 2 | John | john#hotmail.com |
| 2 | Doe | john#hotmail.com |
| 3 | Fred | fred#hatmail.com |
| 3 | Bloggs | fred#hatmail.com |
+--------+--------+------------------+
What I'm struggling to achieve is this:
+--------+---------+---------+------------------+
| userid | detail1 | detail2 | email |
+--------+---------+---------+------------------+
| 1 | Joe | Soap | joe#hotmail.com |
| 2 | John | Doe | john#hotmail.com |
| 3 | Fred | Bloggs | fred#hatmail.com |
+--------+---------+---------+------------------+
Could you please help and point me in the right direction?
SELECT id,
MAX(CASE WHEN detaildid=1 THEN detail END) as detail1,
MAX(CASE WHEN detaildid=2 THEN detail END) as detail2,
email
FROM users
LEFT JOIN user_detail
ON users.id=user_detail.userid
GROUP BY id,email
ORDER by id
This can be written dynamically if you have many detailids.
You can join the same table twice, once for detail id 1 and another instance for detail id 2
SELECT id, d1.detail, d2.detail, email
FROM users u
LEFT JOIN user_detail d1
ON u.id = d1.userid
AND d1.detailid = 1
LEFT JOIN user_detail d2
ON u.id = d2.userid
AND d2.detailid = 2
ORDER BY ID

MYSQL add row and count from diffrent table

I have mysql database with two tables.
First (information)
+---------+------+----------+
| species | sex | user |
+---------+------+----------+
| bird | NULL | 1 |
| bird | f | 1 |
| cat | f | 1 |
| cat | m | 1 |
| dog | f | 1 |
| dog | m | 2 |
| hamster | f | 2 |
| snake | m | 1 |
+---------+------+----------+
Second (users)
+--------+-----+
| user | id |
+--------+-----+
| amy | 1 |
| dav | 2 |
| mot | 3 |
| mmm | 4 |
| aaw | 5 |
| dsa | 6 |
+--------+-----+
I want to count and show values from table "information" for each user row on table "users"
Like this
+---------+------+----------+
| user | id | count |
+---------+------+----------+
| amy | 1 | 6 |
| dav | 2 | 2 |
| mot | 3 | 0 |
| mmm | 4 | 0 |
| aaw | 5 | 0 |
| dsa | 6 | 0 |
+---------+------+----------+
How can I do this query?
select users.user, users.id, count (species.name)
from users left join species
on users.id = species.user
group by users.user, users.id
order by count (species.name) desc
Isn't it something like:
select u.user, u.id, count(i.user)
from user u
inner join information i on i.user = u.id
group by u.user, u.id