I have 3 tables; events, memberEvents, and members.
Events: eventId, eventName, eventDivision
memberEvents: memberID, eventOne, eventTwo, eventThree, eventFour, eventFive
member: memberID, memberFirstName, memberLastName
I am trying to get it to display events.eventName followed by the memberFirstName & memberLastName of members that are doing that event
This is the query I have been trying:
SELECT * FROM events, memberEvents, members
WHERE events.eventDivision = 'C'
RIGHT JOIN memberEvents.memberID
ON events.eventID = memberEvents.eventOne
OR events.eventID = memberEvents.eventTwo
OR events.eventID = memberEvents.eventThree
OR events.eventID = memberEvents.eventFour
OR events.eventID = memberEvents.eventFive
When I run this i get "#1066 - Not unique table/alias: 'memberEvents'"
Try:
SELECT ev.*, me.* FROM events ev
RIGHT JOIN memberEvents me
ON (ev.eventID = me.eventOne
OR ev.eventID = me.eventTwo
OR ev.eventID = me.eventThree
OR ev.eventID = me.eventFour
OR ev.eventID = me.eventFive)
WHERE ev.eventDivision = 'C'
Did you specifically want to limit the number of events per member to five? Why not just have a memberEvent table that has a primary key made up of foreign keys to member and event?
memberEvent: memberId, eventId
Then your query would be
SELECT
event.eventName,
member.memberFirstName,
member.memberLastName
FROM
event
INNER JOIN
memberEvent
ON
memberEvent.eventID = event.eventId
INNER JOIN
member
ON
memberEvent.memberId = member.memberId
WHERE
event.division = 'C';
Maybe you have a good reason for the table structure you have chosen but it is a denormalised design and if you ever need to increase the number of events per member you'll need to modify your schema and code to suit.
I think you should have a closer look at the defenition
JOIN Syntax
It seems that you have misunderstood the JOIN syntax.
SELECT *
FROM table1 t1 right join
table2 t2 on t1.key1 = t2.key1
and t1.key2 = t2.key2
where t1.somecolumn = somevalue
Related
Now I want to get a comments list, and I have two table named TB_COMMENT, TB_USER;
the TB_COMMENT table has three fields: WORK_ID, USER_ID, ATED_USER_ID;
the TB_USER table has three fields: USER_ID, NICKNAME.
now the front end gives me a workId, and I need to return the list include:
userId, nickname, atedUserId, atedNickname.(and the atedUserId, atedNickname may not exist).
And I just write this sql sentence:
SELECT DISTINCT TB_USER.USER_ID, TB_USER.NICKNAME, TB_COMMENT.ATED_USER_ID
FROM TB_USER, TB_COMMENT
WHERE TB_COMMENT.WORK_ID = #{workId} AND TB_COMMENT.USER_ID = TB_USER.USER_ID`
and I don't know how to get the atedNickname. Hope someone can help me, thanks.
You need one more join with TB_USER on ATED_USER_ID foreign key
SELECT DISTINCT ua.USER_ID, ua.NICKNAME, ub.USER_ID, ub.NICKNAME
FROM TB_USER ua INNER JOIN TB_COMMENT c ON ua.USER_ID = c.USER_ID
LEFT JOIN TB_USER ub ON ub.USER_ID = c.ATED_USER_ID
WHERE c.WORK_ID = #{workId}
MySQL Table Diagram:
My query this far:
SELECT tblcourses.CourseStandard,
tblcourses.CourseID,
tblcourses.CourseRef,
tblcourses.CourseStandard,
tblcourses.CourseName,
tblcourses.CourseDuration,
tblcourses.NQFLevel,
tblcourses.CoursePrice,
tblcoursestartdates.StartDate
FROM etcgroup.tblcoursestartdates tblcoursestartdates
INNER JOIN etcgroup.tblcourses tblcourses
ON (tblcoursestartdates.CourseID = tblcourses.CourseID)
WHERE tblcoursestartdates.StartDate >= Now()
If you look at the diagram you will see I have a 3rd table. The query above works fine. It display all the data as it should.
I want to show all the courses and their respective dates excluding those that the student is already booked for. Keep in mind that there can be 20 start dates for 1 course. This is why I am only choosing dates >= Now().
I want to make sure that a student does not get double booked. Yes I can do it afterwards. Beep student already booked BUT if I can have it now show the course dates that the student already booked then great. Any suggestions?
This is pretty straightforward. Presumably you know the StudentID you'd like to see. Do a left join to the bookings table and select the mismatches.
SELECT tblcourses.CourseStandard,
tblcourses.CourseID,
tblcourses.CourseRef,
tblcourses.CourseStandard,
tblcourses.CourseName,
tblcourses.CourseDuration,
tblcourses.NQFLevel,
tblcourses.CoursePrice,
tblcoursestartdates.StartDate
FROM etcgroup.tblcoursestartdates tblcoursestartdates
INNER JOIN etcgroup.tblcourses tblcourses
ON tblcoursestartdates.CourseID = tblcourses.CourseID
AND tblcoursestartdates.StartDate >= Now()
LEFT JOIN tblbookings
ON tblbookings.CourseId = tblcourses.CourseId
AND tblbookings.StudentId = <<<the student ID in question >>>
WHERE tblbookings.BookingID IS NULL
The trick here is the LEFT JOIN ... IS NULL pattern. It eliminates the rows where the ON condition of the LEFT JOIN hit, leaving only the ones where it missed.
Do a left join to tblBookings on courseID where the bookingID is null (there are no matches). You'll have to provide the studentID as a parameter to the query.
SELECT DISTINCT c.CourseStandard,
c.CourseID,
c.CourseRef,
c.CourseStandard,
c.CourseName,
c.CourseDuration,
c.NQFLevel,
c.CoursePrice,
d.StartDate
FROM etcgroup.tblcoursestartdates d
INNER JOIN etcgroup.tblcourses c ON d.CourseID = c.CourseID
LEFT JOIN etcgroup.tblBookings b on c.CourseID = b.CourseID and b.StudentID = #StudentID
WHERE d.StartDate >= Now() and b.bookingID is null
Use NOT EXISTS or NOT IN to find the courses a student has already booked:
SELECT
c.CourseStandard,
c.CourseID,
c.CourseRef,
c.CourseStandard,
c.CourseName,
c.CourseDuration,
c.NQFLevel,
c.CoursePrice,
csd.StartDate
FROM etcgroup.tblcourses c
INNER JOIN etcgroup.tblcoursestartdates csd ON csd.CourseID = tblcourses.CourseID
WHERE csd.StartDate >= Now()
AND c.CourseID NOT IN
(
SELECT CourseID
FROM tblbookings
WHERE StudentID = 12345
);
For a medical calendar, I've got the following query:
SELECT
`events`.`StartDate`,
`events`.`ID`,
`events`.`EndDate`,
`events`.`Title`,
`insurances`.`Title`,
`personsPatients`.`PrimaryPhone`,
`personsDocs`.`Name`
FROM `events`
LEFT JOIN `events++persons` ON `events`.`ID` = `events++persons`.`FirstEntityID` AND `events++persons`.`Type` = 'Patient'
LEFT JOIN `persons` AS `personsPatients` ON `events++persons`.`SecondEntityID` = `personsPatients`.`ID`
LEFT JOIN `insurances` ON `persons`.`Provider` = `insurances`.`ID`
LEFT JOIN `events++persons` AS `events++persons1` ON `events`.`ID` = `events++persons1`.`FirstEntityID` AND `events++persons1`.`Type` = 'Doctor'
LEFT JOIN `persons` AS `personsDoctors` ON `events++persons`.`SecondEntityID` = `personsDoctors`.`ID`
LEFT JOIN `companies++events` ON `events`.`ID` = `companies++events`.`SecondEntityID`
WHERE
((`events`.`Type` = 'Annotation' and `companies++events`.`FirstEntityID` IS NULL) or
(`events`.`Type` = 'Annotation' and `companies++events`.`FirstEntityID` = 1) or
(`events`.`Type` = 'Consultation' and `companies++events`.`FirstEntityID` = 1)) and
`events`.`StartDate` >= '2015-03-02 00:00:00' AND
`events`.`StartDate` <= '2015-03-07 23:59:59'
ORDER BY `events`.`StartDate` ASC
Events are linked via events++persons to two persons: A doctor and a patient.
This query is enormously slow.
When I remove the ORDER BY (which is essential), the filesort and the temp table vanish. Any help is greatly appreciated!
The problem lies with companies++events - all the one-to-one LEFT JOINs in the world don't help when the criterion comes only at the end. I managed to move that info into the main entity (kind of like a pointer) and create a covering index, now the query is lightning-fast.
Doing a bit of investigation and writing a query against a logs db.
I've joined a number of tables to bring back the data that I need, but i'd like to clean it up a bit.
The query returns all the users and which features they have enabled on their account.
Here is what i'm trying to do to clean it up:
Their is a column called 'actions' which has two states, 'added' and 'removed'
If a user feature has an action of 'removed' then I want to not show any of the rows for the same feature for that user which are also marked as 'added'
Is this possible?!
Here is what I have so far:
select users.id as site_id, users.company_name, feature_log.featurecode, feature.minimum_account as feature_type, users.account_type as site_type, account_types.name as account, feature_log.action, feature_log.time
from users
inner join
feature_log
on users.id = feature_log.siteid
inner join
feature
on feature_log.featurecode = feature.featurecode
inner join account_types
on users.account_type_INC = account_types.id
where feature.minimum_account != 0
AND feature.minimum_account > users.account_type
AND users.status = 'Y'
ORDER BY feature_log.time DESC
Thanks for any support!
So, in order to "mute" all the features, that have been "removed" at any point in time for a given user, you can add a (left) join on the following subquery:
SELECT DISTINCT users.id as siteid, feature_log.featurecode, TRUE as mute_feature
FROM users
INNER JOIN feature_log ON (users.id = feature_log.siteid)
WHERE action = 'removed'
This will be the list of features that a given user disabled at some point in time. Then in your query's WHERE clause, you'd add a filter like so:
AND NOT IFNULL(mute_feature, FALSE)
Essentially, that'd bring your whole query to be:
select users.id as site_id, users.company_name, feature_log.featurecode, feature.minimum_account as feature_type, users.account_type as site_type, account_types.name as account, feature_log.action, feature_log.time
from users
inner join
feature_log
on users.id = feature_log.siteid
left join (
SELECT DISTINCT users.id as siteid, feature_log.featurecode, TRUE as mute_feature
FROM users
INNER JOIN feature_log ON (users.id = feature_log.siteid)
WHERE action = 'removed'
) as muted_features ON (feature_log.siteid = muted_features.siteid AND feature_log.featurecode = muted_features.featurecode)
inner join
feature
on feature_log.featurecode = feature.featurecode
inner join account_types
on users.account_type_INC = account_types.id
where feature.minimum_account != 0
AND feature.minimum_account > users.account_type
AND users.status = 'Y'
AND NOT IFNULL(mute_feature, FALSE)
ORDER BY feature_log.time DESC
I'm using the following query to return all duplicate records with the same first and last name. The trick is that the contact_id, has to be in descending order.
The query returns the contacts as expected, but it is just SO SLOW! Takes about 6-8 seconds when checking around 30,000 records.
I have the contact_firstName, contact_lastName, contact_client_id, and contact_id all indexed in the database.
Any ideas what I could do to try and speed this up a bit? Thanks for your help :)
SELECT z.contact_id, z.contact_firstName, z.contact_lastName, RIGHT(z.contact_lastName,1) AS nameNum
FROM (`contacts` x)
JOIN `contacts` z ON `x`.`contact_firstName` = `z`.`contact_firstName`
AND x.contact_lastName = z.contact_lastName
AND x.contact_client_id = ".$ID."
AND z.contact_client_id = ".$ID."
WHERE `x`.`contact_id` < `z`.`contact_id`
GROUP BY `z`.`contact_id`
Not making any promises, but here's an alternative to try:
SELECT c.contact_id, c.contact_firstName, c.contact_lastName, RIGHT(c.contact_lastName,1) AS nameNum
FROM (SELECT contact_firstName, contact_lastName, MIN(contact_id) AS MinID
FROM contacts
WHERE contact_client_id = ".$ID."
GROUP BY contact_firstName, contact_lastName
HAVING COUNT(*) > 1) t
INNER JOIN contacts c
ON t.contact_firstName = c.contact_firstName
AND t.contact_lastName = c.contact_lastName
AND c.contact_client_id = ".$ID."
AND t.MinID <> c.contact_id
SELECT z.contact_id, z.contact_firstName, z.contact_lastName
, RIGHT(z.contact_lastName,1) AS nameNum
FROM `contacts` x
JOIN `contacts` z ON (x.contact_client_id = z.contact_client_id)
WHERE `x`.`contact_id` < `z`.`contact_id`
And x.contact_client_id = '$id'
GROUP BY `z`.`contact_id`
Make sure you have an index on:
- contact_id.
- contact_client_id