Combine data from 2 "strange" tables - mysql

Having the following Schema
(ER of DataBase)
I am trying to create a query that
will show the title(Movies.Title) along with each movie's genre(movie_Genres.movie_genre) for each movie that..
that have been seen in (a) a specific time period (lets say 2-3 days for ex. We can take those days from the Tickets.ticket_date) (b) by Male Customers(Customer.customer_sec) and (c) got rated more than 4 (rated_customerRation) by those customers.
I can get as close as the following query:
SELECT
`movie_title`, `movie_Genres`.`movie_genre`
FROM
`Movies`
INNER JOIN
`movie_Genres` ON `mg_movie` = `movie_ID`
INNER JOIN
`Rated` ON `rated_movie_ID` = `movie_ID`
WHERE `rated_customerRatio` > 4 AND
UNION
(SELECT
`customer_sex`, `rated_customerRatio`
FROM
`Customer`
/* INNER JOIN
`cinema`.`Rated` ON `Rated`.`rated_customer_tabID` = `Customer`.`customer_tabID`
*/
INNER JOIN
`cinema`.`Tickets` ON `Tickets`.`ticket_customer_tabID`=`Customer`.`customer_tabID`
WHERE
`customer_sex` LIKE 'Male'
/* AND rated_customerRatio > 4 */
AND `Tickets`.`ticket_date` > '2016-02-16')
GROUP BY `movie_title`;
Also I am thinking that I will have trouble, cause one movie can have more than one Genre, and I don't want double lines, for the same movie, in my outcome.
Any help will be taken into serious regards!

use a WHERE movie.ID IN (Select movie.id...) query to have unusual query relationships. i.e. if movie.id can be related to tickets
WHERE MovieID IN
(
SELECT
MovieID
FROM
MovieTable
LEFT JOIN TICKETS ON MovieID = TICKETS.movieID
LEFT JOIN CUSTOMER ON TICKETS.ID = CUSTOMER.ID
WHERE
CUSTOMER.customer_sex LIKE 'Male'
AND Tickets.ticket_date > '2016-02-16')
)
I dont know your DB schema but that should give you a rough idea on one way of sorting based on viewership of moves from tickets? 1 ticket should have 1 movie ID and 1 customer, so the relationship is pretty easy to figure out

Related

Optimisation of subqueries

I have a relation between users and groups. Users can be in a group or not.
EDIT : Added some stuff to the model to make it more convenient.
Let's say I have a rule to add users in a group considering it has a specific town, and a custom metadata like age 18).
Curently, I do that to know which users I have to add in the group of the people living in Paris who are 18:
SELECT user.id AS 'id'
FROM user
LEFT JOIN
(
SELECT user_id
FROM user_has_role_group
WHERE role_group_id = 1 -- Group for Paris
)
AS T1
ON user.id = T1.user_id
WHERE
(
user.town = 'Paris' AND JSON_EXTRACT('custom_metadata', '$.age') = 18
)
AND T1.user_id IS NULL
It works & gives me the IDs of the users to insert in group.
But when I have 50 groups to proceed, like for 50 town or various ages, it forces me to do 50 requests, it's very slow and not efficient for my Database.
How could I generate a result for each group ?
Something like :
role_group_id user_to_add
1 1
1 2
2 1
2 3
The only way I know to do that for now is to do an UNION on several sub queries like the one above, but of course it's very slow.
Note that the custom_metadata field is a user defined field. I can't create specific columns or tables.
Thanks a lot for your help.
if I good understood you:
select user.id, grp.id
from user, role_group grp
where (user.id, grp.id) not in (select user_id, role_group_id from user_has_role_group) and user.town in ('Paris', 'Warsav')
that code give list of users and group which they not belong from one of towns..
To add the missing entries to user_has_role_group, you might want to have some mapping between those town names and their group_id's.
The example below is just using a subquery with unions for that.
But you could replace that with a select from a table.
Maybe even from role_group, if those names correlate with the user town names.
insert into user_has_role_group (user_id, group_id)
select u.user_id, g.group_id
from user u
join (
select 'Paris' as name, 1 as group_id union all
select 'Rome', 2
-- add more towns here
) g on (u.town = g.name)
left join user_has_role_group ug
on (ug.user_id = u.user_id and ug.role_group_id = g.group_id)
where u.town in ('Paris','Rome') -- add more towns here
and json_extract(u.custom_metadata, '$.age') = 18
and ug.id is null;

How to join any number of tables in MySQL?

I am having a major problem joining 5 tables because each table only has 1 column in common with only 1 other table.
Here are my tables and columns in each table:
TABLE (COLUMNS)
person (person_id, first_name, last name)
building (building_id, building_name)
room (room_id, room_number, building_id, capacity)
meeting (meeting_id, room_id, meeting_start, meeting_end)
person_meeting (person_id, meeting_id)
OK, now here is what I am trying to do (pasted from a homework assignment):
Construct the SQL statement to find all the meetings that person_id #1 has to attend. Display the following columns:
Person’s first name
Person’s last name
Building name
Room number
Meeting start date and time
Meeting end date and time
Now I know how to join 2 tables but I have no idea how to pull info from 5 different tables like this.
I tried looking up how to do this and it just says to do a UNION command, and I am just learning and have yet to cover that.
As UNION is used to combine the result from multiple SELECT statements into a single result set, you don't need it for this scenario. You have to join all the tables one by one based on their Id.
SELECT P.First_Name, P.Last_Name, B.Building_name, R.Room_Number,
M.Meeting_Start, M.Meeting_End FROM Person P
JOIN Person_Meeting PM ON P.Person_Id = PM.Person_Id
JOIN Meeting M ON PM.Meeting_Id = M.Meeting_Id
JOIN Room R ON M.Room_Id = R.Room_Id
JOIN Building B ON R.Building_Id = B.Building_Id
WHERE P.Person_Id = 1

Display all results of SQL query (including where count 0)

I have the following Query:
SELECT airportname, COUNT(DISTINCT foundBag.id) countFound, COUNT(DISTINCT lostBag.id) countLost
FROM airports
INNER JOIN foundBag ON airport_id = foundBag.airportDest
INNER JOIN lostBag ON airport_id = lostBag.airportDest
GROUP BY airport.airportname");
What I have now: A table that has 3 columns: Airport name with the number of bags found and number of bags lost.
It only displays an airport (row) when both of the columns are filled.
I want 2 things:
To display all the airports even when there are no lost / found bags.
To display the airports where the are lost / found bags (so when 1 or both the columns are filled)
I tried this with When etc. but it keeps giving me errors. I also tried the EXISTS but I'm new to SQL so I do not know how it works...
Does someone have a solution?
Kind regards,
LTKort
This should work for both conditions:
SELECT airportname, COUNT(DISTINCT foundBag.id) countFound, COUNT(DISTINCT lostBag.id) countLost
FROM airports
LEFT JOIN foundBag ON airport_id = foundBag.airportDest
LEFT JOIN lostBag ON airport_id = lostBag.airportDest
WHERE foundBag.airportDest is not null
or lostBag.airportDest is not null
GROUP BY airport.airportname

Optimize SQL to find sports (basketball) lineups

I am trying to setup a SQL database to record the 3 person lineups that have occurred in the game. The structure I have now is:
Player
playerID
playerName
Lineup
lineupID
Lineup_players
lineupID (foreign key)
playerID (foreign key)
I want to find a quick way to check whether a particular set of 3 players are already part of a lineup. Suppose I want to find a lineup with players A,B,C, the solution I can think of is something like:
SELECT t1.lineupID
FROM (SELECT lineupID FROM Lineup_players WHERE playerID=A) t1
INNER JOIN (SELECT lineupID FROM Lineup_players WHERE playerID=B) t2 ON t1.lineupID = t2.lineupID
INNER JOIN (SELECT lineupID FROM Lineup_players WHERE playerID=C) t3 ON t1.lineupID = t3.lineupID
I feel that this is a clumsy solution. Is there a faster query using the same tables, or is there a better way to store the data?
Also, if I have players A,B,C,D,E in my lineup, is there a fast way of finding all lineups with any 3 of these players without checking all 20 combinations?
Maybe you're looking something like this?
select
lineupid,
count(*)
from
Lineup_players
where
playerid in (A,B,C,D,E)
group by
lineupid
having
count(*) >= 3
This will list you the lineups that have 3 or more of the listed ids.

SQL Genius need .. Complex MySQL query

I am trying to optimise my php by doing as much work on the MySQL server as possible. I have this sql query which is pulling data out of a leads table, but at the same time joining two tags tables to combine the result. I am looking to add a company which is linked through a relations table.
So the table that holds the relationship between the two is relations_value which simply states (I add example data)
parenttable (companies) | parentrecordid (10) | childtable (leads) | childrecordid (1)
the companies table has quite a few columns but the only two relevant are;
id (10) | companyname (my company name)
So this query currently grabs everything I need but I want to bring the companyname into the query:
SELECT leads.id,
GROUP_CONCAT(c.tag ORDER BY c.tag) AS tags,
leads.status,
leads.probability
FROM `gs_db_1002`.leads
LEFT JOIN ( SELECT *
FROM tags_module
WHERE tagid IN ( SELECT id
FROM tags
WHERE moduleid = 'leads' ) ) as b
ON leads.id = b.recordid
LEFT JOIN `gs_db_1002`.tags as c
ON b.tagid = c.id
GROUP BY leads.id,
leads.status,
leads.probability
I need to be able to go into the relations_values table and pull parenttable and parentrecordid by selecting childtable = leads and childrecordid = 1 and somehow join these so that I am able to get companyname as a column in the above query...
Is this possible?
I have created a sqlfiddle: sqlfiddle.com/#!2/023fa/2 So I am looking to add companies.companyname as column to the query.
I don't know what your primary keys and foreign keys are that link each table together.. if you could give a better understanding of what ID's are linked to eachother it would make this a lot easier... however i did something that does return the correct result... but since all of the ID's are = 1 then it could be incorrect.
SELECT
leads.id, GROUP_CONCAT(c.tag ORDER BY c.tag) AS tags,
leads.status, leads.probability, companyname
FROM leads
LEFT JOIN (
SELECT * FROM tags_module WHERE tagid IN (
SELECT id FROM tags WHERE moduleid = 'leads' )
) as b ON leads.id = b.recordid
LEFT JOIN tags as c ON b.tagid = c.id
LEFT JOIN relations_values rv on rv.id = b.recordid
LEFT JOIN companies c1 on c1.createdby = rv.parentrecordid
GROUP BY leads.id,leads.status, leads.probability