How to write a proper If...Else Statement with JOIN in MySQL? - mysql

I'm quite a beginner in MySQL I just know the totally basic statements, however now I'ts time for me to get into some more difficult, but worth stuff.
I actually have 3 tables in MySQL, here is the representation:
users:
user_id | name | country
---------------------------
1 | Joseph | US
2 | Kennedy | US
3 | Dale | UK
admins:
admin_id | name | country
----------------------------
1 | David | UK
2 | Ryan | US
3 | Paul | UK
notes:
id | n_id | note | comment | country | type | manager
----------------------------------------------------------------
1 | 3 | This is the 1st note | First | US | admin | 2
2 | 2 | This is the 2nd note | Second | US | user | 1
3 | 2 | This is the 3rd note | Third | UK | user | 2
Now I would like to execute something like this SQL (I'm going to type not real commands here, because I'm not really familiar with all of the SQL expressions):
IF notes.type = admin
THEN
SELECT
notes.note,
notes.comment,
notes.country,
admins.name,
admins.country
FROM notes, admins
WHERE notes.n_id = admin.admin_id
ELSEIF notes.type = 'user'
SELECT
notes.note,
notes.comment,
notes.country,
users.name,
users.country
FROM notes, users
WHERE notes.n_id = users.user_id
I hope you understand what would I like to achieve here. I could do this easily with more SQL statements, but I would like to try some query which doesn't use that much resources.
Edit 1:
I would like to Get all of the Notes and get which usergroup has submitted it than apply the user's name to it. I mean, if the admin submitted the note, than SQL should choose the ID from the Admin table (as per the type value) but if a User submitted the note, it should get the name from the Users table.
The result should look something similar to this:
result:
------
id | note | comment | country | name
--------------------------------------------------------
1 | This is the 1st note | First | US | Paul
2 | This is the 2nd note | Second | US | Kennedy
3 | This is the 3rd note | Third | UK | Kennedy
Edit 2:
I have actually forgot to mention, that all of these should be listed to a manager. So a 'manager ID' should be added to the Notes and list all of the notes where the manager is for example: 2.

Here is a method that you can do in one query:
SELECT n.note, n.comment, n.country,
coalesce(a.name, u.name) as name, coalesce(a.country, u.country) as country
FROM notes n left join
admins a
on n.n_id = a.admin_id and n.type = 'admin' left join
users u
on n.n_id = u.user_id and n.type = 'user';
This uses left join to bring the records together from both tables. It then chooses the matching record for the select.
To select a particular manager, remove the semicolon and add:
where n.manager = 2;

If you expect admins and users in one result you have got several options. The simplest way is to make a union select like this:
SELECT
notes.note,
notes.comment,
notes.country,
admins.name,
admins.country
FROM
notes join admins on notes.n_id = admin.admin_id
WHERE
notes.manager = 2
UNION ALL
SELECT
notes.note,
notes.comment,
notes.country,
users.name,
users.country
FROM
notes join users on notes.n_id = users.user_id
WHERE
notes.manager = 2

Related

Trying to find duplicates and who made them

I'm working on a legacy system that allowed the insertion of multiple entries with the same email. In the people table are present entries with same name and email and also different name with an already used email (es. the user didn't know or didn't ask the email address to the person and chose to put a fake one).
A person could subscribe to a User multiple times yearly basis
They asked me for a report of which users entered the most of these entries.
Let's say I have 3 tables
| people| | subscriptions| |users|
| ------| |--------------| |-----|
| id | | id | |id |
| name | | personId | |name |
| email | | userId |
| subYear |
I found all duplicate emails and their occurrences using this query
SELECT users.name, people.email, count(subscriptions.id) nSub
FROM people
INNER JOIN (SELECT email, count(id) occurrences
FROM people
where email is not null and email != ""
GROUP BY email
HAVING occurrences > 1) duplicates
ON people.email = duplicates.email
JOIN subscriptions ON people.id = subscriptions.personId
JOIN users on users.id = subscriptions.userId
group by users.name, people.email;
but now I'm stuck when I have to integrate users, the query gives incorrect results or gets stuck in a loop.
I'm sure I'm getting the grouping wrong but I got lost
The result I'm trying to achieve is something like (based on data provided in fiddle)
|users.name| people.email | occurrences |
|----------|-------------------------|-------------|
| User1 | example#example.com | 1 |
| User2 | example#example.com | 2 |
| User2 | fake#email.com | 3 |
| User3 | fake#email.com | 1 |
Any suggestion you can give me is welcome. Thank's in advance
UPDATE: Sorry for the sloppiness, I created a fiddle
sql-fiddle

Using nested SELECT result for IN statement of another nested SELECT

Be gentle. I'm a high school principal coding on the side for our school site.
I have looked at answers, here, here, and here. I might just not know enough to ask the right question.
We have events that have multiple sessions and there are workshops that can be associated with multiple sessions in multiple events.
I'm trying to get a csv result, later to be put into an array, for the associated sessions and events for my Workshops.
The query below works without the second nested Select statement.
In the Alt_Events statement, I need to pull the Event_IDs that are associated with the Session_IDs that are pulled from the first nested Select.
Events
ID | Name | Description
1 | Flex Learning | A day of flexible learning.
2 | Moonshot Expo | A day to join partners to solve problems.
Event_Sessions
ID | Event_ID | Name | Description
1 | 1 | Morning Session | The first session of the day.
2 | 1 | Afternoon Session | The afternoon session.
3 | 1 | Tutoring Session | A chance to get help from teachers.
4 | 2 | Partner Field Trip | The first session of the day.
5 | 2 | Brainstorming Session | The afternoon session.
6 | 2 | Tutoring Session | A chance to get help from teachers.
Event_Workshops
ID | Name | Description
1 | Math Tutorial | Get help from your math teachers.
Event_Workshop_Links
ID | Workshop_ID | Session_ID
1 | 1 | 3
2 | 1 | 6
Output Table:
ID | Name | Description | ... | Alt_Sessions | Alt_Events
1 | Math Tutorial | Get help... | ... | 3,6 | 1,2
Here is my query.
SELECT
ws.ID, ws.Name, ws.Description, ws.Location, ws.Owner_ID, ws.Max_Attendees,
ws.Eng_Major_Allowed, ws.Eng_Minor_Allowed,
ws.HC_Major_Allowed, ws.HC_Minor_Allowed,
ws.IT_Major_Allowed, ws.IT_Minor_Allowed,
u.LastName as Owner_LastName, u.FirstName AS Owner_FirstName, u.Email AS Owner_Email,
(SELECT group_concat(SESSION_ID) FROM Events_Workshops_Links WHERE Workshop_ID = ws.ID) AS Alt_Sessions,
(SELECT group_concat(Event_ID) FROM Event_Sessions WHERE Session_ID IN Alt_Sessions) AS Alt_Events
FROM Event_Workshops as ws
LEFT JOIN users AS u
ON ws.Owner_ID = u.ID
WHERE ws.ID = ?
ORDER BY ws.Name
I need to be able to pull the all event_ids that are in the Alt_Sessions result.
I'm guessing I can't use the result of the first nested query in the second nested query. If that's the problem, how can I pull that list of event ids?
Any and all help is greatly appreciated.
(Updated to show expected output. Also one error in transcribing the query. Session_ID instead of Event_ID in second nested statement.
Use the subquery instead of Alt_Sessions in the IN predicate like below.
(SELECT group_concat(SESSION_ID) FROM Events_Workshops_Links WHERE Workshop_ID = ws.ID) AS Alt_Sessions,
(SELECT group_concat(Event_ID) FROM Event_Sessions WHERE Session_ID IN (SELECT SESSION_ID FROM Events_Workshops_Links WHERE Workshop_ID = ws.ID)) AS Alt_Events
Also, there is a way to make combinations of Alt_Sessions and Alt_Events first and then join to Event_Workshops.
SELECT * FROM Event_Workshops ws
JOIN
(
SELECT
wsl.Workshop_ID,
GROUP_CONCAT(wsl.Session_ID) Alt_Sessions,
GROUP_CONCAT(wsl.ID) Alt_Events
FROM Event_Workshop_Links wsl
GROUP BY wsl.Workshop_ID
) w
ON ws.ID = w.Workshop_ID

Data Between Two Tables

Excuse any novice jibberish I may use to explain my conundrum but hopefully someone here will be able to look past that and provide me with an answer to get me unstuck.
SESSIONS
+--------+---------+----------+
| id | appID | userID |
+--------+---------+----------+
| 1 | 1 | 96 |
+--------+---------+----------+
| 2 | 2 | 97 |
+--------+---------+----------+
| 3 | 1 | 98 |
+--------+---------+----------+
USERS
+--------+---------+
| id | name |
+--------+---------+
| 96 | Bob |
+--------+---------+
| 97 | Tom |
+--------+---------+
| 98 | Beth |
+--------+---------+
For each session in the Sessions table that has an appID of 1, I want to get the users name from the Users table. The Sessions userID column is linked with the Users tables id column.
So my desired result would be:
["Bob", "Beth"]
Any suggestions/help?
try this:
SELECT USERS.name FROM USERS INNER JOIN SESSIONS ON users.id = SESSIONS.userID WHERE SESSIONS.appID = 1
I would read up on http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/ for how all the joins work.
It looks like you forgot to post your code.
But in explanation.... It seems like you can just select the userID from the sessions table and then simply join the users table. Then create a WHERE clause to select all users that are attached to that ID.
Hope it helps.
If you post your code I can probably help you out more and if this doesnt seem just right lemme know and ill help you how i can
You need to create a join table (http://www.tutorialspoint.com/postgresql/postgresql_using_joins.htm) and then request the data using the equal operator.
SELECT USERS.name FROM USERS, SESSIONS WHERE SESSIONS.userID = USERS.ID ;

Join query on Wordpress usermeta

We all love wordpress right?
So I've had to work with the usermeta table that basically have this structure.
umeta_id | user_id | meta_key | meta_value
For some reasons several in-house developer plugins wrote a lot of additional information on this table and lately I won the duty to work with it and pull out some important information that I need to export and save in a structure that actually make sense for a web application.
To provide an example this is the kind of data that I can find:
umeta_id | user_id | meta_key | meta_value
1 | 1 | ourID | asdad878d7a
2 | 1 | country | fooland
3 | 1 | firstname| foo
4 | 1 | lastname | bar
I would like to create a result that resemble this structure:
user_id | ourID | country
1 | asdad878d7a | fooland
I tried something but really this kind of structure isn't something I'm accustomed too.
This is my query so far:
SELECT meta.umeta_id as umeta_id, meta.user_id as user_id, channel.meta_value as ourID, country.meta_value as country
FROM usermeta as meta
INNER JOIN usermeta as channel
INNER JOIN usermeta as country
WHERE channel.meta_key = 'ourID'
AND country.meta_key = 'country'
But the result is basically something wrong. I'm having lots of duplicate of the same user_id, one for every row assigned to the user_id but only reporting the field selected instead of the value. Now while this make sense I don't know how to correctly write this query.
Something like this:
umeta_id | user_id | ourID | country
1 | 51424 | UC6Y94UM6rj | United Kingdom
1 | 51424 | UC6Y94UM6rj | Italy
1 | 51424 | UC6Y94UM6rj | Italy
1 | 51424 | UC6Y94UM6rj | Italy
1 | 51424 | UC6Y94UM6rj | Croatia
1 | 51424 | UC6Y94UM6rj | United States
1 | 51424 | UC6Y94UM6rj | Croatia
Clearly I'm doing something very wrong and I'm here hoping that someone can help me understand how to run this kind of query properly more than having the query done by someone else.
Would this get you closer to what you are looking for?
SELECT meta.umeta_id as umeta_id, meta.user_id as user_id, meta.meta_value as ourID, country.meta_value as country
FROM usermeta as meta
INNER JOIN usermeta as country ON meta.user_id = country.user_id
WHERE meta.meta_key = 'ourID'
AND country.meta_key = 'country'
The logic is to first find an entry that has meta_key 'ourID'. The value of user_id and ourID are picked up from this entry, so the inner join is only required to merge the value of country. The ON condition in INNER JOIN selects the correct country entry.

How to formulate query to show all courses taken by a person

I'm having trouble formulating a MySQL query correctly. Everything I've tried doesn't give me what's needed, or gives a syntax error.
I have three tables: Clients, Courses, and CoursesForClients.
The Clients table just has basic coordinates for a person: ID, Name, Address, email, etc.
+----------+-----------------------------+------+
| ClientID | Name | Address | etc. |
+----------+-----------------------------+------+
| 10 | Joe Smith | 1 Main St. | ... |
| 20 | Bob Smith | 2 Main St. | ... |
| ... | ... ... | ... ... ... | ... |
+----------+-----------------------------+------+
The Courses table stores the course name and its ID.
+----------+-----------------------+
| CourseID | Name |
+----------+-----------------------+
| 100 | Intro. to Subject |
| 200 | Intermediate Subject |
| 300 | Advanced Subject |
| ... | ... ... ... ... |
+----------+-----------------------+
The CoursesForClients table has the CourseID and ClientID. A given Client can have taken multiple courses, so for every course that a Client has taken, there's a row, with the person's ID and the Course ID.
+----------+----------+
| CourseID | ClientID |
+----------+----------+
| 100 | 1 |
| 200 | 1 |
| 300 | 1 |
| 100 | 2 |
| 200 | 2 |
| ... | ... |
+----------+----------+
Now, what I need is to be able to list the Client - just once - together with all the Courses she has taken. So, the result of the query might look like this:
10:Joe Smith
1 Main St.
Somewhere, AL
Intro. to Subject
Intermediate Subject
Advanced Subject
---------------------------
20:Bob Smith
2 Main St.
Somewhere, AL
Intro. to Subject
Intermediate Subject
So this output reflects the relationships between the Client and the Course. The key thing here is that, no matter how many Courses a Client has taken, the Client's particulars appear only once, followed by the list of all the courses she's taken.
There's an additional twist in that there's another table that lists the Grade for the Course for the Client, and that GradeID is also stored in the CoursesForClients table, and there's another table of Grades, with ID and Grade Description. But I won't worry about this right now. For now, all I want is just the basic output shown, as described above.
It looks like it should be easy to set up a query for this, with a JOIN and maybe a GROUP BY, but I'm having a block here and can't seem to get it right. So, any help will be hugely appreciated. Thank you!
SQL deals in tables. By definition a table has a bunch of rows, each of which has the same columns as each other. Your query is going to yield a result set that duplicates the client's information for each course she took.
Your presentation layer is going to format that table, by noticing the first row of each new client and breaking out the client header. You'll do that in php or Java or Crystal Reports or some such presentation tech.
Your query is something like this.
SELECT a.id, a.name, a.address, a.etc,
c.Name
FROM Clients a
JOIN CoursesForClients b USING(ClientID)
JOIN Courses c USING(CourseID)
ORDER BY a.id, c.CourseID
#Strawberry makes a good point about the pitfall of using USING(). Here is the same query on ON.
SELECT a.id, a.name, a.address, a.etc,
c.Name
FROM Clients a
JOIN CoursesForClients b ON a.ClientID = b.ClientID
JOIN Courses c ON b.CourseID = c.CourseID
ORDER BY a.id, c.CourseID