MySQL: LEFT JOIN - mysql

Hello I have 2 tables:
Events (idEvent, eventName)
and
Registrations(idRegistration, idEvent, idPerson)
People register to events and I store their idPerson. Now let's say, we have 2 events (event1 and event2). I am person with id = 1 and I want to see all events and columns that will say me, if I am registered.
I mean output like :
idEvent eventName IamRegistered
1 event1 yes
2 event2 no
How can I write a query from these two tables to see similiar output?
PS: I know SQL syntax but can't figure it out, something with left join probably

You're correct, it is a left join. The CASE expression outputs Yes or No depending upon if a matching record was found.
SELECT e.idEvent, e.EventName, (CASE r.idEvent WHEN NOT NULL THEN 'Yes' ELSE 'No' END) AS IsRegistered FROM Events e
LEFT JOIN Registrations r ON r.idEvent=e.idEvent AND r.idPerson=1
It's important to have the idPerson=1 check in the JOIN clause rather than the Where clause, otherwise events that person 1 is not registred for will not be displayed.

Related

how to show and return zero for data that doesn't appear?

Can you help me with some Queries? I have two kind of table for voting which are choices table and submit table, but there is one more table named topic that related to that both tables. In short I need to get total vote from the submit table for each choices that how many does it appears in that submit table, even if it is doesn't appear so it will return zero.
I have some Queries (kind of a hardcode) that I've tried, it does returns the right voting count but not for the choices that doesn't appear.
SELECT vote_choices.name, vote_choice_submit.created_at,
SUM(CASE WHEN `name` = 'Doe Jhons' THEN 1 ELSE 0 END)+
SUM(CASE WHEN `name` = 'Doe Jhonson' THEN 1 ELSE 0 END)+
SUM(CASE WHEN `name` = 'Doe Doe' THEN 1 ELSE 0 END)
AS 'total_vote'
FROM vote_choice_submit
INNER JOIN vote_choices ON vote_choice_submit.vote_choice_id=vote_choices.choice_id
GROUP by name
ORDER by created_at DESC;
Let's say that Doe Doe doesn't exist in the submit table so I want it to show zero votes. But yet it doesn't appear on the result.
Thanks in advance!
You were using INNER JOIN, so that was the issue
SELECT vc.name, count(vcs.created_at) AS 'total_vote'
FROM vote_choices vc
LEFT OUTER JOIN vote_choice_submit vcs ON vcs.vote_choice_id = vc.choice_id
GROUP by vc.name
If you want to display created_at as well from vote_choice_submit, let me know if you want distinct values for each entry in vote_choice_submit or min/max. The query would need to be rewritten for that.

Updating certain data from one table to another table once a week

My end goal is to update information from table 1 to table 2 on a certain condition. More specifically, I'd like to update the date from table1 to table2 where the id's match and dates from table2 are NULL.
I want this to happen every Sunday.
Here are the specifics:
** Keep in mind, payee_id and id are the same but in two different tables. **
The table I plan to copy from is called orders, but I only want to select certain data from this table. My query looks like this:
TABLE 1
SELECT movement.payee_id,
min(origin_stop.sched_arrive_early) first_date
FROM orders
LEFT JOIN movement_order ON orders.id = movement_order.order_id
LEFT JOIN movement ON movement.id = movement_order.movement_id
LEFT JOIN stop as origin_stop ON origin_stop.id = movement.origin_stop_id
WHERE orders.status <> 'V'
GROUP BY movement.payee_id
OUTPUT 1
payee_id | first_date
-------------------|-----------------
STRINGID1 | 2013-12-20 15:00:00.000
STRINGID2 | 2013-12-27 13:00:00.000
TABLE 2
SELECT id, initial_date
FROM drs_payee
OUTPUT 2
id | initial_date
-------------------|-----------------
STRINGID1 | NULL
STRINGID2 | NULL
TABLE 2 OUTPUT SHOULD BE:
id | initial_date
-------------------|-----------------
STRINGID1 | 2013-12-20 15:00:00.000
STRINGID2 | 2013-12-27 13:00:00.000
My attempt to solve this:
UPDATE drs_payee a
(SELECT movement.payee_id,
min(origin_stop.sched_arrive_early) carrier_first_shipped_date
FROM orders
LEFT JOIN movement_order ON orders.id = movement_order.order_id
LEFT JOIN movement ON movement.id = movement_order.movement_id
LEFT JOIN stop as origin_stop ON origin_stop.id = movement.origin_stop_id
WHERE orders.status <> 'V'
GROUP BY movement.payee_id) b
ON a.id = b.payee_id
SET a.initial_date = b.first_date
WHERE a.initial_date IS NULL
Not sure if the format of this is correct and if you can even do a SELECT inside an UPDATE like shown above.
I believe I have to have a loop to find id's that match (i.e. where payee_id = id and initial_date is NULL). Would this be created in a stored procedure to loop through id's and create a weekly job schedule or would some type of update query be enough? Please help or point me in some direction with the an update query or stored procedure example using my data if possible.
Thanks in advance everyone!
For scheduled queries the best thing for me is creating events. First you have to select your db, and at the top right you'll see an option in phpmyadmin called "events". You have to turn on the events planner, and to do that you mut be logged in with a super privilege user, in phpMyadmin.
After you do that the query is:
DROP EVENT `dates update` ;
CREATE DEFINER = `your_user_name`#`your_host_name`
EVENT `dates update`
ON SCHEDULE EVERY1 WEEK STARTS '2015-07-29 03:00:00'
ON COMPLETION NOT PRESERVE ENABLE DO
UPDATE movement a
INNER JOIN orders b
ON a.payee_id = b.payee_id
SET a.initial_date = b.first_ship_date
WHERE a.initial_date IS NULL;
It must work.
If you need help about super privilege check this
I hope it works for you.
Caio Ortega
Update table2
inner join table1 on payee_id = id
set initial_date=first_date where initial_date is null
Through SQL server agent we can schedule the query as per our requirement (For example every Sunday )

MySQL LEFT JOIN issue: Retrieve workshops names in column A and a row id in column B

Apologies for the rubbish question title, but it's a bit tricky to summarise my requirement into a single line. I usually don't have an issue with MySQL JOINs but this one is throwing me.
I'm building a training feedback system and for one feature would like to display a list of all available workshops in the database, which workshops a given delegate has been assigned to and whether any feedback has been submitted by that delegate for those assigned workshops.
I could do this in a couple of queries, but I'm trying to do something a bit more elegant with a single query.
The pertinent details of my database structure:
WORKSHOPS table
id: INT
name: TINYTEXT
DELEGATES table
id: INT
name: TINYTEXT
FEEDBACK table
delegate_id: INT
workshop_id: INT
feedback: TEXT
DELEGATES_X_WORKSHOPS table
delegate_id: INT
workshop_id: INT
delegate_id and workshop_id in the tables are Foreign Keys to the DELEGATES and WORKSHOPS tables.
As any given delegate can be assigned to multiple workshops, I'm using the DELEGATES_X_WORKSHOPS table as a cross-referencing table so I can quickly search for who is assigned to any given workshop or which workshops any given delegate is assigned to.
However, I've tried LEFT JOINing a couple of different ways and I can't get a full list of workshops on the left and matches (if they exist) on the right for a given delegate_id.
Example data
Delegate Ross has delegate_id = 1
Registered workshops are
C++
PHP
ASP.NET
HTML5
JavaScript
Ross is assigned to PHP, HTML5 and JavaScript
Question 1 is this: how do I return the following for delegate_id=1:
[workshop] | [assigned]
C++ | null
PHP | TRUE
ASP.NET | null
HTML5 | TRUE
JavaScript | TRUE
(it doesn't matter right now what goes into column B, I just want a null if a particular delegate_id hasn't been assigned to a workshop).
I've used this:
SELECT
workshops.name,
delegates_x_workshops.delegate_id
FROM
workshops
LEFT JOIN
delegates_x_workshops
ON
workshops.id=delegates_x_workshops.workshop_id
WHERE
delegates_x_workshops.delegate_id=1
However I'm only returning the 3 rows where delegate_id=1, not 5 rows for all workshops.
Question 2 is a bit more involved:
Taking question 1 as a base, how would I work column C to display if feedback has been left for a workshop that Ross has been assigned to?
[workshop] | [assigned] | [givenfeedback]
C++ | null | null
PHP | TRUE | TRUE
ASP.NET | null | null
HTML5 | TRUE | null
JavaScript | TRUE | TRUE
Thanks in advance to anybody who makes it this far and has a clue what I'm blithering about. As I said, I could rattle through this with a few different queries, but I'm trying to keep things elegant.
No doubt half of this will need clarification, so ask any questions.
Thanks
For question 1, you need to move the where condition into the on clause. It is turning the left outer join into an inner join because non-matching rows have NULL values:
SELECT w.name, dxw.delegate_id
FROM workshops w LEFT JOIN
delegates_x_workshops dxw
ON w.id = dxw.workshop_id and
dxw.delegate_id = 1;
For the second question, I think this is what you want:
SELECT w.name,
(case when max(w.name = 'Ross') > 0 then 'True' end) as Assigned,
(case when count(f.workshop_id) > 0 then 'True' end) as Feedback
FROM workshops w LEFT JOIN
delegates_x_workshops dxw
ON w.id = dxw.workshop_id and
dxw.delegate_id = 1 LEFT JOIN
delegates d
on d.id = dxw.delegate_id LEFT JOIN
feedback f
on f.workshop_id = w.id
GROUP BY w.name;
For reference, here's my final query:
SELECT DISTINCT
workshops.id AS wid,
workshops.name AS workshop,
(delegates_x_workshops.delegate_id IS NOT NULL) AS assigned,
(initial_feedback.delegate_id IS NOT NULL
OR
ongoing_feedback.delegate_id IS NOT NULL) AS hasfeedback
FROM
workshops
LEFT JOIN
delegates_x_workshops
ON
workshops.id = delegates_x_workshops.workshop_id
AND
delegates_x_workshops.delegate_id = 1
LEFT JOIN
initial_feedback
ON
workshops.id = initial_feedback.workshop_id
AND
initial_feedback.delegate_id = 1
LEFT JOIN
ongoing_feedback
ON
workshops.id = ongoing_feedback.workshop_id
AND
ongoing_feedback.delegate_id = 1
ORDER BY
workshop ASC
For every workshop in the WORKSHOPS table, I'll get the id and name of the workshop, 1 or 0 if a given delegate_id is assigned and 1 or 0 if feedback of either type (I have 2 kinds) has been left for that workshop.
Scary to think that all I was missing was an AND condition on my LEFT JOIN.
Thanks again Gordon!

MySQL joining with PHP

Sometimes my eyes goes bonkers with these joins. Please help me build the select statement
product_version
id version
----------------
1 apple
2 orange
3 pineapple
executions
id class methods plat_version orig_prod_version
-----------------------------------------------------------------
1 SomeTest check 2 1
2 AnotTest submit 3 2
I want to pull from the executions but convert the numbers from the version that is in the other table. I was trying to start off and just do one at this point. Here is what I have
SELECT e.id,
e.class,
e.plat_version,
pv.id,
pv.version,
pv.version AS plat_version FROM executions e JOIN product_versions pv ON pv.version = e.plat_version
Thanks for the help.
UPDATE:
I am hoping that it pulls the records from the executions table but instead of seeing numbers for plat_version and orig_prod_version, I want to see corresponding version fields from the other table
I'm thinking something like this:
SELECT
e.id,
e.class,
pv_plat.version AS plat_version,
pv_orig.version AS orig_prod_version,
FROM executions e
JOIN product_versions pv_plat ON pv_plat.id= e.plat_version
JOIN product_versions pv_orig ON pv_orig.id= e.orig_prod_version
The idea is that you just join to the product_versions table twice, once for each id column that you have in the executions table.
SELECT *
FROM executions e
LEFT JOIN product_version v
ON e.plat_version = v.id
LEFT JOIN product_version v2
ON e.orig_prod_version = v2.id
SQL JOIN Explanation

Fetch timestamped counts from multiple tables

I have a table of nodes:
nid type created status
2 blog 134292319 1
3 forum 134292536 1
4 blog 135921392 0
To graph the number of published (status=1) nodes over time, I execute this query:
SELECT created, type
FROM node WHERE status = 1
ORDER BY created
I then go through this data set in PHP, splitting it into timestamped groups with a node count associated with each group. The results are cached, so slow execution isn't a problem.
I also have a table of comments:
nid timestamp status
2 134292363 1
3 134293234 1
I want to incorporate forum comment counts into the graph of node counts.
To get the comment counts, I would run this query:
SELECT timestamp
FROM comments
INNER JOIN node ON comments.nid = node.nid
WHERE
node.type = 'forum'
AND comments.status = 1
ORDER BY timestamp
I need to somehow combine these two queries, to end up with (for the examples given):
created type
134292319 blog
134292536 forum
134293234 forum_comment
Any ideas?
Thanks.
This will get you your example output but I am not sure it's exactly what you are looking for based on your description of the question.
SELECT created, type FROM
(
SELECT created, type
FROM node WHERE status = 1
UNION ALL
SELECT timestamp as created, 'forum_comment' as type
FROM comments
INNER JOIN node ON comments.nid = node.nid
WHERE node.type = 'forum'
AND comments.status = 1
) AS U
ORDER BY U.created