Loop through column and assign 0/1 MySQL - mysql

I have a MySQL database on consumers attending events. The database contains a users table, events table and checkins table which are all connected. But the database only contains info about users going to a certain event.
I want a query that loops through a couple of events and checks if a user went to one of them, and gives as a result:
Preffered result
I've tried with the following query:
select attend.idperson, attend.idmeeting,
(select case when
attend.idmeeting = 2901 or
attend.idmeeting = 9044 or
attend.idmeeting = 9161 or
attend.idmeeting = 2626
then 1 else 0 end) as attended
from attend
join meetings on attend.idmeeting = meetings.idmeeting
join persons on attend.idperson = persons.id
where meetings.verified = 1;
But this brings as a result all meetings where the persons actually went, and assigns a 1 if one of the meetings in the select case when query was attended and a 0 for the rest. The goal is to predict attendance using logistic regression, and this solution makes all further user data biased.

You could build a list of all people and meetings, then left join the attendance details:
select distinct a1.*,
case
when attend.idperson is null then 0
else 1
end as attended
from
(
select meetings.idmeeting, persons.id as p_id
from meetings
cross join persons
where meetings.verified = 1
) a1
left join attend
on attend.idmeeting = a1.idmeetings
and attend.personid a1.p_id

Related

Adding Default Values on Joining Tables

I have the following tables:
Users
user_id course_id completion_rate
1 2 0.4
1 23 0.6
1 49 0.5
... ... ...
Courses
course_id title
1 Intro to Python
2 Intro to R
... ...
70 Intro to Flask
Each entry in the user table represents a course that the user took. However, it is rare that users have taken every course.
What I need is a result set with user_id, course_id, completion_rate. In the case that the user has taken the course, the existing completion_rate should be used, but if not then the completion_rate should be set to 0. That is, there would be 70 rows for each user_id, one for each course.
I don't have a lot of experience with SQL, and I'm not sure where to start. Would it be easier to do this in something like R?
Thank you.
You should first cross join the courses with distinct users. Then left join on this to get the desired result. If the user hasn't taken a course the completion_rate would be null and we use coalesce to default a 0.
select c.course_id,cu.user_id,coalesce(u.completion_rate,0) as completion_rate
from courses c
cross join (select distinct user_id from users) cu
left join users u on u.course_id=c.course_id and cu.user_id=u.user_id
Step1: Take the distinct client_id from client_data (abc) and do 1 on 1 merge with the course data (abc1) . 1 on 1 merge helps up write all the courses against each client_id
Step2: Merge the above dataset with the client info on client_id as well as course
create table ans as
select p.*,case when q.completion_rate is not null then q.completion_rate else 0
end as completion_rate
from
(
select a.client_id,b.course from
(select distinct client_id from abc) a
left join
abc1 b
on 1=1
) p
left join
abc q
on p.client_id = q.client_id and p.course = q.course
order by client_id,course;
Let me know in case of any queries.

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

Mysql Query Search By Dates

I try to create a query which shows available hotels between checkin and checkout dates. Also when I make a reservation for specific rooms, I set their booking column as 1. That means, when the checkout date comes in real life, a trigger function will set that booked column as 0.
If all rooms of a hotel are booked(booked=1) and checkin-checkout dates of those rooms are specific date(checkin-checkout inputs), then don't put that hotel in the list. My query doesn't show the result that I want.
Query: Inputs: Country(state), checkin and checkout.
SELECT DISTINCT a.* FROM accommodation a INNER JOIN cb_states s ON a.state = s.id
INNER JOIN accommodation_rooms ar ON a.id = ar.accommodation
WHERE state = 1 AND a.id NOT IN
(
SELECT 1 FROM booking b
WHERE
(
(b.arrival_date BETWEEN '2017-11-16' AND '2018-03-16')
OR
(b.departure_date BETWEEN '2017-11-16' AND '2018-03-16')
)
)
When I run the query, it always shows all hotels no matter dates. If I write ... WHERE ar.booked = 0 AND state = 1 AND a.id NOT IN..., then it doesn't show accommodation id 13, but it doesn't show either when I change dates.
accommodation table:
accommodation_rooms table:
booking table:
booked_rooms table:(has foreign key with booking table)
You have multiple issues with your query:
The NOT IN list has SELECT 1. That doesn't give a great variety to the NOT IN list.
Your logic for overlaps is wrong.
I think you need to connect accommodation rooms to booked accommodation rooms.
So:
SELECT DISTINCT a.*
FROM accommodation a INNER JOIN
cb_states s
ON a.state = s.id INNER JOIN
accommodation_rooms ar
ON a.id = ar.accommodation
WHERE s.state = 1 AND
a.id NOT IN (SELECT br.accommodation_room
FROM booking b JOIN
booked_room br
ON b.?? = br.??
WHERE b.arrival_date <= '2018-03-16' AND
b.departure_date >= '2017-11-16'
);

SQL query to get records that match ALL the criteria

I need to write a SQL query to get the patients that have stayed in ALL the hospitals of the city where they live. In one city there may be several hospitals of course.
So for example, if the patient 'xxx' who lives in Washington has been in a hospital, I need to list him only if he's been in all the hospitals of Washington and no less.
This is the structure of the tables:
table patient
patientID
patientCity
table hospital
hospitalCode
hospitalCity
table hospital_stay
hospitalCode
patientID
cityStay
What's the most efficient way to do this for MySQL? Thank you!
Unfortunately, MySQL can't order before grouping, so I had to use subquery to order the result correctly before grouping it.
Have fun :)
SELECT * FROM (
SELECT
p.patientID,
hs.hospitalCode
FROM
patient p
INNER JOIN hospital h ON (p.patientCity = h.hospitalCity)
LEFT JOIN hospital_stay hs ON (p.patientID = hs.patientID AND h.hospitalCode = hs.hospitalCode)
ORDER BY 2
) AS tmp_table
GROUP BY 1
HAVING NOT ISNULL(hospitalCode)
This query should work :
Select p.patientID
, p.patientCity
from patient p
inner join hospital h on h.hospitalCity = p.patientCity
inner join hospital_stay hs on hs.hospitalCode = h.hospitalCode
--where hs.cityStay = 1
group by p.patientID, p.patientCity
having count(*) = (select count(*) from hospital
where hospitalCity = p.patientCity);
Remove the comment if cityStay is kind of a flag that says that the patient went to the hospital.

Mysql Multiple ANDS

I have three tables persons, jobs, jobs_persons
One person can have multiple jobs.
Person 1 is Technical Support AND Manager
Person 2 is Technical Support
Person 3 Is Manager
Job 1 Technical Support
Job 2 Manager
I need to find a query give me the result for the person who currently is Technical Support AND Manager
The answer would be only Person 1
SELECT persons.*
FROM persons INNER JOIN jobs_persons ON persons.id = jobs_persons.person_id
INNER JOIN jobs ON jobs.id = jobs_persons.job_id
WHERE job.id IN (1,2)
Returns 3 rows
SELECT persons.*
FROM persons INNER JOIN jobs_persons ON persons.id = jobs_persons.person_id
INNER JOIN jobs ON jobs.id = jobs_persons.job_id
WHERE job.id = 1 AND job.id = 2
Returns 0 rows.
I'm currently working on Ruby on Rails.
Somebody can help?
You want to use an OR operator. Using job.id = 1 AND job.id = 2 will only return elements where id equals 1 and at the same time 2. No element can do that. You want elemets where th id is 1 or where the id is 2.
to make it more obvious:
SELECT * FROM table WHERE lastname = 'Smith' AND firstname = 'James';
when executing this you obviously don't want everybody who is called Smith or James. ;-)
EDIT:
Misread the question. what you need is a second join to join the jobs table two times in and join them with the different jobs. It is a bit hard as you didn't show the schema, but this might work:
SELECT persons.*
FROM persons
INNER JOIN jobs_persons jp1 ON persons.id = jp1.person_id
INNER JOIN jobs_persons jp2 ON persons.id = jp2.person_id
INNER JOIN jobs j1 ON j1.id = jp1.job_id
INNER JOIN jobs j2 ON j2.id = jp2.job_id
WHERE j1.id = 1 AND j2.id = 2
Try this to get all the person who has got a job of 1 AND 2 in your associative entity table. No need to hit the job table.
SELECT p.*
FROM persons p
WHERE id in (
SELECT person_id FROM jobs_persons
WHERE job_id IN (1,2)
GROUP BY person_id
HAVING COUNT(*) = 2
);
With your recent comments, it seems you're having performance problems. That's really outside of the scope of this question and answer.
You need to make sure your indexes are in place on the appropriate columns:
jobs_person.job_id
persons.id