I have a database with two strong entities, and three weak entities. The weak entities only have foreign key references to the primary key of the strong tables they related to, to create an association between the tables.
I have a query selecting from one table the way I want, but am not sure how to go about selecting from all three tables at once and displaying the data in one query.
ERD:
I have tried many different joins and can not get them to work properly. This select displays the information that I want for one table:
select f.FilmName, concat(p.FirstName, ' ', p.LastName) as Producer
from filmtable as f
inner join persontable as p
inner join produced;
I would like to be able to select and display all the information from all three weak tables, in a format similar to:
FilmName, Producer, ScreenWriter, Director.
You need:
select f.FilmName, concat(ppr.FirstName, ' ', ppr.LastName) as Producer,
concat(psw.FirstName, ' ', psw.LastName) as ScreenWriter,
concat(pdir.FirstName, ' ', pdir.LastName) as Director
from filmtable as f
left join produced as prod ON prod.FilmID = f.FilmID
left join Directed as dir ON dir.FilmID = f.FilmID
left join ScreenWote as sw ON sw.FilmID = f.FilmID
left join persontable as ppr ON prod.PersonID = ppr.personID
left join persontable as psw ON sw.PersonID = psw.personID
left join persontable as pdir ON dir.PersonID = pdir.personID;
Alternate solution is to use sub queries in SELECT statement to achieve all 3 parties i.e. Producer, Writer and Director, in one row.
SELECT f.FilmName,
(
SELECT concat(p.FirstName, ' ', p.LastName)
FROM persontable AS pt
JOIN produced AS a
ON pt.PersonID = a.PersonID
WHERE p.FilmID = f.FilmID
) AS producer,
(
SELECT concat(p.FirstName, ' ', p.LastName)
FROM persontable AS pt
JOIN screenwrote AS a
ON pt.PersonID = a.PersonID
WHERE p.FilmID = f.FilmID
) AS ScreenWriter,
(
SELECT concat(p.FirstName, ' ', p.LastName)
FROM persontable AS pt
JOIN directed AS a
ON pt.PersonID = a.PersonID
WHERE p.FilmID = f.FilmID
) AS Director
FROM filmtable AS f
Related
This is my SQL query I am trying to select the names of employees from the employee table 'T' as trainer and 'S' as student. Where each student is linked to a trainer.
SQL query:
SELECT
cc.CourseName,
FORMAT(cs.StartDate, 'dd/MM/yyyy') AS 'Start Date',
FORMAT(cs.EndDate, 'dd/MM/yyyy') AS 'End Date',
a.AcademyName,
r.RoomName,
(SELECT e.FirstName + ' ' + e.LastName WHERE e.EmployeeType = 'T') AS 'Trainer',
(SELECT e.FirstName + ' ' + e.LastName WHERE e.EmployeeType = 'S') AS 'Student'
FROM
Employees e
INNER JOIN
CourseScheduleTrainers cst ON e.EmployeeID = cst.EmployeeID
INNER JOIN
CourseScheduleAttendees csa ON cst.TrainerID = csa.TrainerID
INNER JOIN
CourseCatalog cc ON csa.CourseCatalogID = cc.CourseCatalogID
INNER JOIN
CourseSchedule cs ON cc.CourseScheduleID = cs.CourseScheduleID
INNER JOIN
Rooms r ON cs.RoomsID = r.RoomsID
INNER JOIN
Academies a ON r.AcademyID = a.AcademyID;
This is what it is returning:
And this is an ERD of the database I am am trying to create. Essentially Course Attendees can also be classed as employees and they are labelled using the Employee Type
Entity Relationship Diagram:
I thought it was a simple case of sub querying but that doesn't seem to work.
Consider joining Employees twice and re-order the FROM and JOIN clauses to start with the main granular table, CourseScheduleAttendees, where other tables serve as lookups in a hub-spoke fashion:
SELECT cc.CourseName
,FORMAT(cs.StartDate, 'dd/MM/yyyy') AS 'Start Date'
,FORMAT(cs.EndDate, 'dd/MM/yyyy') AS 'End Date'
,a.AcademyName
,r.RoomName
,t.FirstName + ' ' + t.LastName AS 'Trainer'
,s.FirstName + ' ' + s.LastName AS 'Student'
FROM CourseScheduleAttendees csa
INNER JOIN CourseScheduleTrainers cst
ON csa.TrainerID = cst.TrainerID
INNER JOIN Employees t
ON cst.EmployeeID = t.EmployeeID
AND t.EmployeeType = 'T'
INNER JOIN Employees s
ON csa.AttendeeID = s.EmployeeID
AND s.EmployeeType = 'S'
INNER JOIN CourseCatalog cc
ON csa.CourseCatalogID = cc.CourseCatalogID
INNER JOIN CourseSchedule cs
ON cc.CourseScheduleID = cs.CourseScheduleID
INNER JOIN Rooms r
ON cs.RoomsID = r.RoomsID
INNER JOIN Academies a
ON r.AcademyID = a.AcademyID;
I have 3 tables in my db
1)cushbu_users (id,first_name,last_name)
2)cushbu_art (id,user_id(FK cushbu_user),title,base_price etc...) -for store user arts
3)cushbu_mark_user_favorites (id,user_id(FK cushbu_user),art_id(FK cushbu_art)) -for marking favourite items
I want to fetch the all art items of a particular user favourited
with count of favourites each art (stored in cushbu_mark_usier_favorites table )
Here is my query
SELECT
cushbu_art.id AS art_id,
cushbu_art.title,
cushbu_art.base_price,
cushbu_art.image_name,
CONCAT(
cushbu_users.first_name,
' ',
cushbu_users.last_name
) AS artist_name,COUNT(cushbu_mark_user_favorites.art_id)
FROM
cushbu_art
JOIN cushbu_mark_user_favorites ON cushbu_mark_user_favorites.art_id = cushbu_art.id
JOIN cushbu_users ON cushbu_users.id = cushbu_art.artist_id
LEFT JOIN cushbu_mark_user_favorites ON cushbu_art.id=cushbu_mark_user_favorites.art_id
WHERE
cushbu_mark_user_favorites.user_id = 68
But i got Not unique table/alias: 'cushbu_mark_user_favorites' this join statement
LEFT JOIN cushbu_mark_user_favorites ON cushbu_art.id=cushbu_mark_user_favorites.art_id
UPDATE
SELECT
a.id AS art_id,
a.title,
a.base_price,
a.image_name,
CONCAT(
c.first_name,
' ',
c.last_name
) AS artist_name,COUNT(b.art_id)
FROM
cushbu_art a
JOIN cushbu_mark_user_favorites b ON b.art_id = a.id
JOIN cushbu_users c ON c.id = a.artist_id
LEFT JOIN b ON a.id=b.art_id
WHERE
b.user_id = 68
Try below query.
SELECT
cushbu_art.id AS art_id,
cushbu_art.title,
cushbu_art.image_name,
CONCAT(
cushbu_users.first_name,
' ',
cushbu_users.last_name
) AS artist_name , b.favorites_count as total_fav
FROM
cushbu_mark_user_favorites
LEFT JOIN cushbu_art ON cushbu_art.id=cushbu_mark_user_favorites.art_id
LEFT JOIN cushbu_users ON cushbu_users.id = cushbu_art.artist_id
LEFT JOIN (SELECT art_id,count(*) as favorites_count FROM cushbu_mark_user_favorites GROUP BY art_id) as b ON b.art_id=cushbu_art.id
WHERE cushbu_mark_user_favorites.user_id=1
GROUP BY cushbu_art.id
Hope this will helpful to you.
As the title states I am trying to Left Join information from table B, but then also show matching information in table A, thats not associated in table B. Below is my query but it's currently only returning the inner join.
SELECT
concat(u.firstname, ' ', u.lastname) AS clientName,
u.email AS clientEmail,
u.created_at AS signedUp,
u.refferedby AS referredBy,
concat(t.firstname, ' ', t.lastname) AS trainerWho,
t.email AS trainerWhoEmail,
concat(usr.firstname, ' ', usr.lastname) AS clientWho,
usr.email as clientWhoEmail
FROM users u
LEFT JOIN trainers t ON u.externalid = t.hashId
INNER JOIN users usr ON u.externalid = usr.hashId
WHERE u.refferedby IS NOT NULL
AND DATE(u.created_at) >= CURDATE() -7
ORDER BY(u.created_at);
Ok, say I have a database layout similar to the one in the example I have provided. In the above examples movies have releases in languages and those movie_releases also have theatre releases in different theatres.
Now if I wanted to query the database to get all of a movie's theatre releases as well as all movie_releases, how would I do that?
The current code I have is:
select
GROUP_CONCAT(movie.name, ",", language.lang, ",", GROUP_CONCAT(theatre.name)) as releases
from
movie
left join movie_releases on movie_releases.movie_id = movie.id
left join language on movie_release.language_id = language.id
left join theatre_release on theatre_release.movie_release_id = movie_release.id
left join theatre on theatre.id = theatre_release.theatre_id
Obviously this doesn't work because you can't nest GROUP_CONCAT functions like this.
My desired output would be something like
["Spiderman", "English", ["Cinema Theatre", "Garden Cinemas"]]
["Spiderman", "Spanish", ["El Cine Grande"]]
["Batman", "English", ["Town Movies"]]
SELECT
CONCAT(
'["', `movie`.`name`, '"',
', ',
'"', releases.lang, '"',
', [',
releases.theatres,
']]'
) AS `release`
FROM
movie
LEFT JOIN (
SELECT
movie_id,
`language`.lang,
GROUP_CONCAT('"', theatre.`name`, '"') AS theatres
FROM
movie_release
LEFT JOIN theatre_release ON theatre_release.movie_release_id = movie_release.id
LEFT JOIN theatre ON theatre.id = theatre_release.theatre_id
LEFT JOIN `language` ON `language`.id = movie_release.language_id
GROUP BY
movie_id,
language_id
) AS releases ON releases.movie_id = movie.id
You can group the theatres in a subselect and then join them onto the movies by their relation over the releases.
By bringing the data in your format it might make the query a little harder to read. So here is the query without the fancy formatting.
SELECT
CONCAT(
`movie`.`name`,
' ',
releases.lang,
' ',
releases.theatres
) AS `release`
FROM
movie
LEFT JOIN (
SELECT
movie_id,
`language`.lang,
GROUP_CONCAT(theatre.`name`) AS theatres
FROM
movie_release
LEFT JOIN theatre_release ON theatre_release.movie_release_id = movie_release.id
LEFT JOIN theatre ON theatre.id = theatre_release.theatre_id
LEFT JOIN `language` ON `language`.id = movie_release.language_id
GROUP BY
movie_id,
language_id
) AS releases ON releases.movie_id = movie.id
To add the delimiteres you only have to adjust the CONCAT or the GROUP_CONCAT
Thank you for read my quetsion.
I want to know which is the best or correct way to express queries in Rails which make many joins and select attributes from multiple tables:
SELECT
ffca.name,
ffc.name,
ft.title,
concat(s.first_name, ' ', s.last_name),
pf.name,
ft.amount,
date_format(ft.created_at,'%d/%m/%y')
FROM
finance_transactions ft
INNER JOIN students s ON ft.student_id = s.id
INNER JOIN payment_forms pf ON ft.payment_form_id = pf.id
INNER JOIN finance_fees ff ON ft.finance_fees_id = ff.id
INNER JOIN finance_fee_collections ffc ON ff.fee_collection_id = ffc.id
INNER JOIN finance_fee_categories ffca ON ffc.fee_category_id = ffca.id;
If you need extra info, please feel free to ask me.
Thank you very much.
e.g
your model is finance_transactions
finace_transaction = FinanceTransaction.find_by_sql(
"SELECT
ffca.name as name,
ffc.name as name1,
ft.title as title,
concat(s.first_name, ' ', s.last_name) as full_name,
pf.name as pf_name,
ft.amount as count,
date_format(ft.created_at,'%d/%m/%y') as time
FROM
finance_transactions ft
INNER JOIN students s ON ft.student_id = s.id
INNER JOIN payment_forms pf ON ft.payment_form_id = pf.id
INNER JOIN finance_fees ff ON ft.finance_fees_id = ff.id
INNER JOIN finance_fee_collections ffc ON ff.fee_collection_id = ffc.id
INNER JOIN finance_fee_categories ffca ON ffc.fee_category_id = ffca.id"
)
the table finance_transactions table must have column name, name1,title, full_name,pf_name, count, time
and then you can use:
finace_transaction.name1 gets ffc.name
You might want to provide a method in your model class as a wrapper
class FinanceTransaction < ActiveRecord::Base
[...]
def self.find_fee_transactions
self.find_by_sql(<<-SQL)
SELECT
ffca.name as name,
ffc.name as name1,
ft.title as title,
concat(s.first_name, ' ', s.last_name) as full_name,
pf.name as pf_name,
ft.amount as count,
date_format(ft.created_at,'%d/%m/%y') as time
FROM
finance_transactions ft
INNER JOIN students s ON ft.student_id = s.id
INNER JOIN payment_forms pf ON ft.payment_form_id = pf.id
INNER JOIN finance_fees ff ON ft.finance_fees_id = ff.id
INNER JOIN finance_fee_collections ffc ON ff.fee_collection_id = ffc.id
INNER JOIN finance_fee_categories ffca ON ffc.fee_category_id = ffca.id"
)
SQL
end
end