How to join three table to check the data in sql? - mysql

I know how to join two tables to check data, but I not sure how to join the third table. I have tried to find solution in the online, but I can't find solution it can match my problem. Hope someone can guide me how to join the third table. Thanks.
Below is my sql code, this sql code just to join two tables:
SELECT bl.id_book_name as bl_book_name
, bl.remark as bl_remark
, bl.status as status
, bl.return_date as bl_return_date
, anb.country as anb_country
, anb.title as book_name
, bl.date_borrowed as date_borrowed
FROM book_lending bl
JOIN add_new_book anb
ON bl.id_book_name = anb.id
My third table column in the below, table name is called user, I want to join the user name:
id |name |
This is my join two tables testing result:

Since you have not provided the full structure of USER table, I can only provide you the glimpse of joining third table. You may try below code -
SELECT bl.id_book_name as bl_book_name
, bl.remark as bl_remark
, bl.status as status
, bl.return_date as bl_return_date
, anb.country as anb_country
, anb.title as book_name
, bl.date_borrowed as date_borrowed
FROM book_lending bl
JOIN add_new_book anb ON bl.id_book_name = anb.id
JOIN user u ON u.id = <USER_ID column in 1 of above 2 tables>

Related

Access or Mysql - Table rows as columns in query

I have these three tables:
The table "Clienti" contains the customers.
The table "Corsi" contains all the available courses
The table "corsi Fatti" contains all the Courses each client has taken.
what I would need is a query that returns each client, and what courses he attended on what date.
For that I would like to have for example a table returned with these columns:
Clienti.Nome, corsi.row1.corso, corsi.row2.corso, corsi.row3.corso,corsi.rowN.corso.
and the content of the table should be:
clienti.Nome, corsifatti.data of the matching course in the corsi table if present.
so, first column is the client name, and then there is a column for each row of the "corsi" table, and if a client has partecipated on that course then the corsifatti.data should be in that column.
Can something like this be done with a Access or Mysql Query? I have tried with inner joins but the result was not what I need.
select
Clienti.nome, Clienti.Addresse, Clienti.CAP, Clienti.Tel,
Clienti.Ansprechpartner, Clienti.Mail, Clienti.Weiteres,
CorsiFatti.Data, Corsi.Corso, Corsi.Durata
from Clienti
INNER JOIN CorsiFatti on CorsiFatti.[ID Cliente] = Clienti.ID
INNER JOIN Corsi on Corsi.ID = CorsiFatti.[ID Corso]
What you are asking is a simple inner join:
select Clienti.nome, Clienti.Addresse, Clienti.CAP,
Clienti.Tel, Clienti.Ansprechpartner, Clienti.Mail,
Clienti.Weiteres,
CorsiFatti.Data,
Corsi.Corso, Corsi.Durata
from Clienti
INNER JOIN CorsiFatti on CorsiFatti.[ID Cliente] = Clienti.ID
INNER JOIN Corsi on Corsi.ID = CorsiFatti.[ID Corso]
order by Clienti.nome, Corsi.Corso;
I think you meant yours was lacking the order by only.
I wouldn't suggest using access, but if it is access anyway, then you need to have parenthseses around all those joins (peculiar I know, but it is access).
The pivot with variable columns count is complicated. I can advice simplest solution uses JSON aggregation:
SELECT
ClienteId,
Name,
JSON_ARRAYAGG(
JSON_OBJECT("Data", Data, "Corso", Corso)
) Corsi
FROM
CorsiFatti
JOIN Corsi ON Corsi.Id = CorsiFatti.CorsoId
JOIN Clienti ON Clienti.Id = CorsiFatti.clienteId
GROUP BY
ClienteId,
Name
;
Result is row for each client contains client's data at his courses as JSON string:
+===========+=========+========================================================================================+
| ClienteId | Name | Corsi |
+===========+=========+========================================================================================+
| 1 | Mr. Fix | [{"Data": "2021-01-01", "Corso": "Corso1"}, {"Data": "2021-02-01", "Corso": "Corso3"}] |
+-----------+---------+----------------------------------------------------------------------------------------+
Here you can find SQL fiddle

Inner join in combination with sum and group by

I am having some strange issue with the SQL statement below. The result groups by user IDs and some of them turn out right but for one of them (user ID = 1) the "initial_average" is multiplied by 3. I really have no idea why.. Is there something wrong with the structure of the statement? If it is not clear, the aim is to sum the field "initial_avg" in the "tasks" table and have it broken out by user. Some help with this is much appreciated. I am using MySQL.
SELECT sum(initial_avg) AS initial_average
, sum(initial_std) AS initial_standard_dev
, tasks.user
, hourly_rate
FROM tasks
INNER JOIN user_project
ON tasks.user=user_project.user
AND tasks.project=59
AND tasks.user=1
GROUP BY tasks.user
I just solved it by adding another "and" clause (AND user_project.project=59 )
Optimize your query (Try it):
SELECT SUM(initial_avg) AS initial_average, SUM(initial_std) AS initial_standard_dev, tasks.user, hourly_rate FROM tasks INNER JOIN user_project ON tasks.user = user_project.user AND tasks.project = User_project.project WHERE tasks.project = 59 AND tasks.user = 1 GROUP BY tasks.user, hourly_rate

SQL JOIN 2 TABLE WITH CONDITION (DATE)

I have 2 tables 'barang_jadi' and 'stok_barang'. I'll show all data from table 'barang_jadi' join with 'stok_barang where stok_barang.tanggal='04-04-2015'' plus show all data from table 'barang_jadi'.
here I try, but I still don't have solution. http://sqlfiddle.com/#!9/306e6/1/0
IMAGES TABLE WHEN I USING MY QUERY
Do you want something like this?
select barang_jadi.*, stok_barang.*
from barang_jadi
left join stok_barang on barang_jadi.no=stok_barang.kode_barang where tanggal is null or tanggal = '04-04-2015'

MySQL Join different tables

I am trying to join the following tables with the following code, but I can't join the last columns.
Table:magazine
id_mag **mag_name** id_freq
Table:frequency
id_freq **freq_name**
Table:copy
id_mag **id_copy** **copy_date** copy_price copy_page_number
Table:article
id_art **art_name** **art_page_number**
Table:copy_art
id_mag **id_copy** id_art article_page_num
I want to show a table with the following columns. The columns in the tables magazine, frequency, copy, article & copy_art that have ** ** are the ones I am interested in to be showed:
mag_name freq_name id_copy copy_date art_name art_page_number
I got the following table with this code:
SELECT * FROM magazine
JOIN frequency ON magazine.id_freq = frequency.id_freq
JOIN copy_art ON revista.id_mag=copy_art.id_mag
JOIN article ON copy_art.id_art=article.id_art
JOIN copy ON copy_art.id_copy=copy.id_copy;
Here is the translation for the name of each column that appears in the image:
id_rev = id_mag
nom_rev = mag_name
id_frec = id_freq
nom_frec = freq_name
id_rev = id_mag
id_ejem = id_copy
id_art = id_art
num_pag = article_page_num
nom_art = art_name
num_pag_art = art_page_number
fecha_ejem = copy_date
precio = copy_price
My doubt is the following:
What should I do in order to have the table with?
mag_name freq_name id_copy copy_date art_name article_page_num
Thanks a lot for your kindly support!
If you only want a few columns in the output, then you have to list which columns you do want. The key structure of the data is unclear (meaning it isn't clear which columns are the primary keys of each table); you have the id_mag and id_copy columns both appearing in copy and copy_art and it isn't entirely clear whether they're a composite key or id_copy is sufficient. Given that we don't have that information, we'll have to take your SELECT statement and its joins as gospel, but I'm not convinced that's correct.
You wrote:
SELECT *
FROM magazine
JOIN frequency ON magazine.id_freq = frequency.id_freq
JOIN copy_art ON revista.id_mag=copy_art.id_mag
JOIN article ON copy_art.id_art=article.id_art
JOIN copy ON copy_art.id_copy=copy.id_copy;
This collects all the columns from all the tables mentioned, which is wasteful. So, you need to specify which columns you do want:
SELECT m.mag_name, f.freq_name, c.id_copy, c.copy_date, a.art_name, a.art_page_number
FROM magazine AS m
JOIN frequency AS f ON m.id_freq = f.id_freq
JOIN copy_art AS y ON m.id_mag = y.id_mag
JOIN article AS a ON y.id_art = a.id_art
JOIN copy AS c ON y.id_copy = c.id_copy;
I'm not entirely sure that you need the copy_art table in the query, but I'm assuming you know your data better than I do.
You have to make sure that one of the first tables has got a foreign key for the articulo table to join that as well.
If you add that (For example in the revista table), you can make a JOIN over all tables with something like this:
SELECT * FROM revista
JOIN frecuencia ON revista.id_frec = frecuencia.id_frec
JOIN ejemplar ON revista.id_rev = ejemplar.id_rev
JOIN articulo ON revista.id_art = articulo.id_art;
See this fiddle for an example (I query * here, you can change that to just the columns that you need).

Sql Result IN a Query

dont blame for the database design.I am not its database architect. I am the one who has to use it in current situation
I hope this will be understandable.
I have 3 tables containing following data with no foreign key relationship b/w them:
groups
groupId groupName
1 Admin
2 Editor
3 Subscriber
preveleges
groupId roles
1 1,2
2 2,3
3 1
roles
roleId roleTitle
1 add
2 edit
Query:
SELECT roles
from groups
LEFT JOIN preveleges ON (groups.groupId=preveleges.groupId)
returns specific result i.e roles.
Problem: I wanted to show roleTitle instead of roles in the above query.
I am confused how to relate table roles with this query and returns required result
I know it is feasible with coding but i want in SQL.Any suggestion will be appreciated.
SELECT g.groupName,
GROUP_CONCAT(r.roleTitle
ORDER BY FIND_IN_SET(r.roleId, p.roles))
AS RoleTitles
FROM groups AS g
LEFT JOIN preveleges AS p
ON g.groupId = p.groupId
LEFT JOIN roles AS r
ON FIND_IN_SET(r.roleId, p.roles)
GROUP BY g.groupName ;
Tested at: SQL-FIDDLE
I would change the data structure it self. Since It's not normalised, there are multiple elements in a single column.
But it is possible with SQL, if for some (valid) reason you can't change the DB.
A simple "static" solution:
SELECT REPLACE(REPLACE(roles, '1', 'add'), '2', 'edit') from groups
LEFT JOIN preveleges ON(groups.groupId=preveleges.groupId)
A more complex but still ugly solution:
CREATE FUNCTION ReplaceRoleIDWithName (#StringIds VARCHAR(50))
RETURNS VARCHAR(50)
AS
BEGIN
DECLARE #RoleNames VARCHAR(50)
SET #RoleNames = #StringIds
SELECT #RoleNames = REPLACE(#RoleNames, CAST(RoleId AS VARCHAR(50)), roleTitle)
FROM roles
RETURN #RoleNames
END
And then use the function in the query
SELECT ReplaceRoleIDWithName(roles) from groups
LEFT JOIN preveleges ON(groups.groupId=preveleges.groupId)
It is possible without function, but this is more readable. Made without editor so it's not tested in anyway.
You also tagged the question with PostgreSQL and it's actually quite easy with Postgres to work around this broken design:
SELECT grp.groupname, r.roletitle
FROM groups grp
join (
select groupid, cast(regexp_split_to_table(roles, ',') as integer) as role_id
from privileges
) as privs on privs.groupid = grp.groupid
join roles r on r.roleid = privs.role_id;
SQLFiddle: http://sqlfiddle.com/#!12/5e87b/1
(Note that I changed the incorrectly spelled name preveleges to the correct spelling privileges)
But you should really, really re-design your data model!
Fixing your design also enables you to define foreign key constraints and validate the input. In your current model, the application would probably break (just as my query would), if someone inserted the value 'one,two,three' into the roles table.
Edit
To complete the picture, using Postgres's array handling the above could be slightly simplified using a similar approach as MySQL's find_in_set()
select grp.groupname, r.roletitle
from groups grp
join privileges privs on grp.groupid = privs.groupid
join roles r on r.roleid::text = any (string_to_array(privs.roles, ','))
In both cases if all role titles should be shown as a comma separated list, the string_agg() function could be used (which is equivalent to MySQL's group_concat()
select grp.groupname, string_agg(r.roletitle, ',')
from groups grp
join privileges privs on grp.groupid = privs.groupid
join roles r on r.roleid::text = any (string_to_array(privs.roles, ','))
group by grp.groupname