SQL Inner Join statement not giving desired results - mysql

Hopefully someone can give me a hand here. I have the following two tables:
Table: locations
location_id user_id city state
1 1 Los Angeles CA
2 1 New York NY
3 1 Chicago IL
4 2 Dallas TX
5 3 Denver CO
6 4 Miami FL
7 5 Atlanta GA
Table: events
event_id user_id event_name event_date
1 1 My Event 1 2017-02-01
2 2 My Event 2 2017-03-01
3 3 My Event 3 2017-04-01
4 4 My Event 4 2017-05-01
5 5 My Event 5 2017-06-01
I am running the following query:
SELECT e.event_id, e.user_id, e.event_name, e.event_date,
l.user_id, l.city, l.state
FROM events e
INNER JOIN locations l
ON e.user_id = l.user_id
ORDER BY e.event_date ASC
I am trying just to get JUST the records in the events table, but also pull the corresponding city and state that match the user_id that both tables have in common. The output should be:
event_id user_id event_name event_date city state
1 1 My Event 1 2017-02-01 Los Angeles CA
2 2 My Event 2 2017-03-01 Dallas TX
3 3 My Event 3 2017-04-01 Denver CO
4 4 My Event 4 2017-05-01 Miami FL
5 5 My Event 5 2017-06-01 Atlanta GA
Can anyone point me to my error in the SQL statement?

You never gave us the logic for deciding which location to choose for a given user. One approach would be to take the minimum location_id associated with a given user:
SELECT t1.*,
COALESCE(t2.city, 'NA'),
COALESCE(t2.state, 'NA')
FROM events t1
LEFT JOIN locations t2
ON t1.user_id = t2.user_id
INNER JOIN
(
SELECT user_id, MIN(location_id) AS min_location_id
FROM locations
GROUP BY user_id
) t3
ON t2.user_id = t3.user_id AND
t2.location_id = t3.min_location_id

That's quite impossible, here the issue is for user with id 1 you have 3 tuples in the locations table , which city to select is the big question.
1 1 Los Angeles CA
2 1 New York NY
3 1 Chicago IL

Related

Join two tables with Mapping and get result

I'm use HBase DB with phoenix, I have 3 tables in which two are Main table which have many to many relation ship between them which is mapped by the third table.
Employee
EmpID EmpName
1 Robert
2 John
3 Sansa
4 Ned
5 Tyrion
6 George
7 Daenerys
8 Arya
9 Cersie
10 Catelyn
Department
DepID DepName
1 Hardware
2 Software
3 Admin
4 HR
Department_Employee_Mapping
ID DepID EmpID
1 1 2
2 1 6
3 2 1
4 3 5
5 3 6
6 4 3
7 4 7
8 4 10
9 4 5
I want to get names and department of all the employees who are in Admin Department, but also I want the details of those employee who belong to other department and who do not belong to any of the departments and these data should appear as NULL in the resultset Only the value for admin department should appear and if the employee belong to multiple departments, the result set should contain the value the Admin department and the other one will be ignored, Result set will look like
Emp Name Dep Name
Robert NULL
John NULL
Sansa NULL
Ned NULL
Tyrion Admin
George Admin
Daenerys NULL
Arya NULL
Cersie NULL
Catelyn Admin
Use 2 LEFT JOIN and include the filtering on 'Admin' in the join against Department
SELECT DISTINCT e.empname, d.depname
FROM Employee e
LEFT JOIN Department_Employee_Mapping x ON x.empid = e.id
LEFT JOIN Departmentd ON d.id = x.depid AND d.id = 3

Mysql Fetch Records When Foreign Key Value Is Zero

I've created some tables as follows.
countries
con_id con_name
99 India
100 China
cities
cty_id cty_name country_id
1 Bangalore 99
2 Chennai 99
3 Delhi NCR 99
fees
f_id st_dt end_dt city_id country_id
1 2014-05-05 2014-05-05 1 99
2 2014-05-10 2014-05-10 2 99
3 2014-05-15 2014-05-15 3 99
4 2014-05-20 2014-05-20 0 100
5 2014-05-22 2014-05-22 0 100
I'm writing a query fetch the records from fees table by country_id as follows.
SELECT *
FROM fees as fe
JOIN countries as con
ON con.con_id = fe.country_id
JOIN cities as cty
ON cty.cty_id = fe.city_id
For country india, it fetches first 3 records from fees table and for country china, its not fetching any records due to joinings.
So I want the results like null for city columns and correct values for fees and country tables.
Please help me how to get the solution for this. The work would be more appreciated.
You can use LEFT JOIN (or right, depending on the join sequence):
SELECT *
FROM countries c
LEFT JOIN fees f
ON c.con_id = f.country_id
LEFT JOIN cities ci
ON ci.country_id = c.con_id
The left join will fill with nulls the columns which don't have a match in the join.

How to check if records within selected date using multiple tables?

It is an additional question to my previous one that is already answered.
There are 4 tables: buildings, rooms, reservations, information
1 building = n rooms
1 room = n reservations
TABLE BUILDINGS - ID(int), name(varchar)
TABLE ROOMS - ID(int), building_id(int)
TABLE RESERVATIONS - ID(int), room_id(int), date_start(datetime), date_end(datetime)
TABLE INFORMATION - ID(int), building_id(int), hours_start(int), hours_end(int)
Buildings table example
ID name
1 Building A
2 Building B
3 Building C
Rooms table example
ID building_id
1 1
2 1
3 2
4 3
Reservations table example
ID room_id date_start date_end
1 1 2014-08-09 14:00:00 2014-08-09 14:30:00
2 1 2014-08-09 14:30:00 2014-08-09 15:30:00
3 3 2014-08-09 16:30:00 2014-08-09 17:30:00
4 2 2014-08-09 16:00:00 2014-08-09 17:00:00
5 3 2014-08-09 16:00:00 2014-08-09 16:30:00
Information table example
ID building_id hours_start hours_end
1 1 9 22
2 2 8 20
3 3 8 22
Question
Can we filter buildings that has atleast 1 available room on selected date in any hour? Buildings working hours may be different (Information table).
I think this will do what you want. It calculates the total number of meeting hours in the building for all the rooms. It then calculates the total meeting hours. If a room is available the second is less than the first:
SELECT b.id, b.name,
sum(timestampdiff(minute, rv.date_start, rv.date_end))/60 as MeetingHours,
max(hours_end - hours_start)*count(distinct r.id) as BuildingHours
FROM buildings b JOIN
information bi
on b.id = bi.building_id
rooms r
ON b.id = r.building_id LEFT JOIN
reservations rv
ON rv.room_id = r.id AND
'2014-08-09' between date(rv.date_start) AND date(rv.date_end)
GROUP BY b.id
HAVING MeetingHours is Null or MeetingHours < BuildingHours;

Getting multiple results in a single query

I need to know student - student ID, first name, last name. Those have not seen an event at a particular given Auditorium. I have to list these students in ascending last name order (through one query). Run the query twice, showing results for the Auditorium “London Theatre” in one run and “Brentwood Hall” in the second run.
I have no clue what this first and second run means. Also please check if the below will work for first run. I am thinking of creating a view and storing the first run, and writing the same query with "Brentwood Hall" and storing it in the second view. However, how will I display 2 views as part of same query then?
SELECT op.StudentID
, s.FirstName
, s.LastName
FROM auditorium a
JOIN audievent e
ON a.auditoriumID = e.AuditoriumID
JOIN reserver r
ON e.EventID = r.EventID
JOIN OrderProcessor op
ON r.OrderID = op.OrderID
JOIN Student s
ON op.StudentID = s.StudentID
WHERE op.StudentID NOT IN ( SELECT DISTINCT op.StudentID
FROM OrderProcessor op
LEFT
JOIN reserver r
ON op.OrderID = r.OrderID
LEFT
JOIN AudiEvent e
ON r.AuditoriumID = e.AuditoriumID
WHERE e.EventID NOT IN ( SELECT EventID FROM reserver)
)
AND a.AuditoriumName = 'London Theatre'
GROUP
BY op.StudentID;
OUTPUT:-
StudentID FirstName LastName
ID1 Andy Hall
ID2 Andy Halls
ID3 Mush Peters
ID4 Garry Hiegl
INPUT:-
Auditorium
AudiID AudiName
Audi01 London Theatre
Audi02 Brentwood Hall
Audi03 County Hall
AudiEvent
EventID AudiID
1 Audi01
2 Audi01
3 Audi01
4 Audi01
5 Audi01
6 Audi01
7 Audi01
8 Audi01
9 Audi01
10 Audi01
11 Audi02
12 Audi02
13 Audi02
14 Audi02
15 Audi02
16 Audi03
17 Audi03
18 Audi03
19 Audi03
20 Audi03
Reserver
ReserverID OrderID AudiID EventID
1 1 Audi01 1
2 1 Audi01 2
3 2 Audi01 3
4 2 Audi01 4
5 2 Audi02 14
6 3 Audi02 15
7 3 Audi02 11
8 4 Audi03 18
9 4 Audi03 19
10 4 Audi03 20
OrderProcessor
OrderID StudentID
1 ID01
2 ID02
3 ID03
4 ID04
Student
StudentID FirstName LastName
ID1 Andy Hall
ID2 Andy Halls
ID3 Mush Peters
ID4 Garry Hiegl
As #wildplasser mentioned, NOT EXISTS is perfect for this:
SELECT studentId, student.firstName, student.lastName
FROM Student
WHERE NOT EXISTS (SELECT 1
FROM OrderProcessor
JOIN Reserver
ON Reserver.orderId = OrderProcessor.orderId
JOIN AudiEvent
ON AudiEvent.eventId = Reserver.eventId
JOIN Auditorium
ON Auditorium.audiId = AudiEvent.audiId
AND Auditorium.audiName = 'London Theatre'
WHERE OrderProcessor.studentId = Student.studentId)
(working SQL Fiddle example)
The necessary changes to get students who haven't seen events at the 'Brentwood Hall' is left as an exercise to the reader.

Add total of 3 rows for specific id

I have three tables:
Students
-------------------------------------------------------------
studentId first last gender weight
-------------------------------------------------------------
1 John Doe m 185
2 John Doe2 m 130
3 John Doe3 m 250
Lifts
-------------------
liftId name
-------------------
1 Bench Press
2 Power Clean
3 Parallel Squat
4 Deadlift
5 Shoulder Press
StudentLifts
------------------------------------------------
studentLiftId studentId liftId weight
------------------------------------------------
1 1 1 185
2 2 3 130
3 3 1 190
4 1 2 120
5 2 1 155
6 3 2 145
7 1 1 135
8 1 1 205
9 2 3 200
10 1 3 150
11 2 2 110
12 3 3 250
I would like to have four top lists:
Bench Press
Parallel Squat
Power Clean
Total of the above 3
I can successfully grab a top list for each specific lift using the following query:
SELECT s.studentId, s.first, s.last, s.gender, s.weight, l.name, sl.weight
FROM Students s
LEFT JOIN (
SELECT *
FROM StudentLifts
ORDER BY weight DESC
) sl ON sl.studentId = s.studentId
LEFT JOIN Lifts l ON l.liftId = sl.liftId
WHERE l.name = 'Bench Press'
AND s.gender = 'm'
AND s.weight > 170
GROUP BY s.studentId
ORDER BY sl.weight DESC
However, I am stuck on how to add the highest total of each lift for each student. How can I first find the highest total for each student in each lift, and then add them up to get a total of all three lifts?
Edit
The result set that I am looking for would be something like:
-------------------------------------------------
studentId first last weight
-------------------------------------------------
3 John Doe3 585
1 John Doe 475
2 John Doe2 465
I also forgot to mention that I would actually like two lists, one for students above 170 and one for students below 170.
SELECT -- join student a total weight to the student table
A.studentId,
A.first,
A.last,
C.totalWeight
FROM
Student A,
(
SELECT -- for each studet add the max weights
sum(B.maxWeight) as totalWeight,
B.studentID
FROM (
SELECT -- for each (student,lift) select the max weight
max(weight) as maxWeight,
studentId,
liftID
FROM
StudentLifts
GROUP BY
studentId,
liftID
) B
GROUP BY
studentId
) C
WHERE
A.studentID = C.studentId
-- AND A.weight >= 170
-- AND A.weight < 170
-- pick one here to generate on of the two lists.