Using IN operator with a subquery - mysql

Having the following scheme
CREATE TABLE request (
`id` int,
`classroom` varchar(255),
`school` varchar(255),
`date_of_application` datetime,
`status` varchar(100),
`user_id` bigint(20) NOT NULL
);
CREATE TABLE user (
`id` int,
`full_name` varchar(255)
);
CREATE TABLE user_schools (
`user_id` int,
`schools_string` varchar(255)
);
I need to obtain a list of requests where the status field is equal to 'pending' and where the school field is located in the list of schools associated with a user
Right now i am trying the following query
SELECT
r.id,
u.full_name,
r.date_of_application,
r.classroom
FROM
request r
inner join
user u on u.id = r.user_id
WHERE
r.school IN (
SELECT
us.schools_string
FROM
user_schools us
WHERE
us.user_id = u.id
)
AND r.status = 'pending';
I currently get the total list of requests. I understand what is failing is the subquery.
Attached a sqlfiddle to facilitate your collaboration
The result I expect are three applications where applicants are: user user, user user and another assistant user
Thanks for any idea. If there is a better solution, I thank you.
Regards

The code is doing what you are asking. If you want user/requests that are in the list, then you can use select distinct like this:
SELECT DISTINCT u.full_name, r.date_of_application
FROM request r inner join
user u
on u.id = r.user_id
WHERE r.school IN (SELECT us.schools_string
FROM user_schools us
WHERE us.user_id = u.id
) AND
r.status = 'pending';
But if you want the classroom and request id, then you are going to get your original result set (or some variation).

Related

Referencing Two Tables in SQL DB

I'm new to SQL, how could I answer the following question? Do I use join?
Thank you so much.
What are the names and home cities for people searched for the word "drain"?
.schema is below:
CREATE TABLE `users` (
`id` INTEGER,
`name` VARCHAR,
`email` VARCHAR,
`city` VARCHAR,
`state` VARCHAR,
`last_visit` DATE,
`page_views` INTEGER,
PRIMARY KEY (`id`)
);
CREATE TABLE `search_terms` (
`id` INTEGER,
`word` VARCHAR,
PRIMARY KEY (`id`)
);
select u.name, u.city
from users u
inner join search_terms st on st.id = u.id
where st.word = 'drain'
I hope this helps.
You do need to join search_terms table with users table. I assume the search_terms.id is referencing to users.id.
Linking them both, will give us the results of the search terms for each user.
from there you can add more filters (WHERE conditions) to have more specific results.
So, to get the names and the home cities for each user you need to select name and city from users table, then join search_terms table and link id columns to know what words that each user has used in the search.
The query should be something like this :
SELECT name, city
FROM users
LEFT JOIN search_terms ON search_terms.id = users.id
WHERE
search_terms.word LIKE 'drain';
You could use a JOIN or a sub-query. Here's the basic strategy:
Get the id values that match what you're looking for
Look up any other info for those id values
.
SELECT name, city
FROM users usr
INNER JOIN search_terms stm ON usr.id = stm.id
WHERE stm.word = 'drain';
or ...
SELECT name, city
FROM users
WHERE id IN (SELECT id FROM search_terms WHERE word = 'drain');

mysql find recent user comments (part 2)

Cont. on mysql find recent user comments
Again, 2 tables:
create table user(
userID int auto_increment,
userName varchar(10),
userCreatedDate timestamp,
primary key(userID)
);
create table comment(
commentID int auto-increment,
userID int,
comment varchar(100),
primary key(commentID),
foreign key(userID) references user(userID)
);
This time the userCreateDate and commentID value is different from part 1.
And I want to find recent comment from the database.
My output like the following:
Here is the query that I tried:
select u.userID, max(c.commentID) as commentID, c.comment, u.userCreatedDate
from comment c
left join user u on c.userID = u.userID
group by u.userID
order by u.userCreateDate desc
However, I can't get my output.
Can someone help me?
You can do this as below and is called group wise max/min http://dev.mysql.com/doc/refman/5.7/en/example-maximum-column-group-row.html
select u.*,c.comment from user u
join comment c on c.userID = u.userID
join (
select max(commentID) as commentID,userID
from comment group by userID
)c1 on c1.commentID = c.commentID
try this query :-
select u.userID,commentID, c.comment, u.userCreatedDate
from comment c
left join user u on c.userID = u.userID
WHERE commentID=(SELECT MAX(c2.commentID)
FROM comment c2
WHERE c.userID = c2.userID)

Get all conversations from one user in different chats MYSQL

I am working on a facebook style chat and am trying to get all the latest conversations from one user with other users.
Right now I am getting all the latest conversations but in the case that the other user has written to me. What I want to do is for example I have 2 conversations, conversation 1 is the latest I wrote into, but now I write into conversation 2, when I refresh the page conversation 2 will be first.
Now if the other person of conversation 1 writes me, if I refresh page conversation 1 will be first.
This are the 2 tables I am working with:
CREATE TABLE users (
id int(255) not null auto_increment,
username varchar(150) null,
email varchar(150) null,
password varchar(255) null,
salt varchar(255) null,
pic varchar(255) not null,
primary key(id)
) ENGINE = INNODB DEFAULT CHARSET=utf8;
CREATE TABLE chat (
id int(255) not null auto_increment,
id_us int(255) not null,
id_receptor int(255) not null,
message varchar(3000) not null,
chat_date datetime not null,
primary key (id),
index chatUsId(id_us),
index chatRecId(id_receptor),
foreign key (id_us) references users(id) on delete cascade,
foreign key (id_receptor) references users(id) on delete cascade
) ENGINE = INNODB DEFAULT CHARSET=utf8;
And this is the query I am using
SELECT m.id_us, m.id_receptor, u.username, u.pic
FROM users AS u, chat AS m
WHERE (m.id_us = u.id AND m.id_receptor =:id_us or m.id_receptor = u.id AND m.id_us =:id_us)
AND m.chat_date = (SELECT MAX( c.chat_date ) FROM chat AS c WHERE m.id_us = c.id_us AND m.id_receptor = c.id_receptor )
group by u.username
ORDER BY m.id DESC
In this case :id_us could be for example 1
I know its not correct as it is not doing what I would like it to do, but I've been struggling trying to find the way to get the results as I want, but I am stucked, any help will be apreciated.
To explain myself better, what I am trying to do is for example when you chat in facebook, the facebook messages list to view your latest conversations.
OK how about this: (using 123 for id of user1)
select T1.user2_id, users.username, users.pic, max(cdate) maxDate from
(select chat.id_receptor user2_id, max(chat_date) cdate
from chat
where chat.id_us=123
group by chat.id_receptor
union distinct
(select chat.id_us user2_id, max(chat_date) cdate
from chat where chat.id_receptor = 123
group by chat.id_us)) T1
inner join users on (users.id = T1.user2_id)
group by T1.user2_id
order by maxDate desc
I want recent message also like whatsapp, and I have update your query as per my tables.
select T1.user2_id, message, user_profile.user_name, user_profile.avatar, max(cdate) message_date from (select messages.receiver_id user2_id, messages.message, (message_date) cdate from messages where messages.sender_id=2 group by messages.receiver_id union distinct(select messages.sender_id user2_id, messages.message, max(message_date) cdate from messages where messages.receiver_id = 2 group by messages.sender_id)) T1 inner join user_profile on (user_profile.id = T1.user2_id) group by T1.user2_id order by message_date desc
Just added another SELECT + JOIN. Please refer to below and let me know if any questions, will try to answer.
I would like to note that even though the above answer is marked is correct, in my understanding it does not covers the full needs of requested query as does not display the key item - i.e. last message per each chat.
$sql="
SELECT T2.maxDate, T2.user2_id, T2.ava, T2.userName,chat.user_to,chat.user_from,chat.body,chat.viewed FROM (SELECT T1.user2_id, users.userName, users.ava, max(cdate) maxDate FROM
(SELECT chat.user_to user2_id, max(msg_time) cdate
FROM chat WHERE chat.user_from=18
GROUP BY chat.user_to
union distinct
(SELECT chat.user_from user2_id, max(msg_time) cdate
FROM chat WHERE chat.user_to=18
GROUP BY chat.user_from)) T1
inner join users on (users.userID = T1.user2_id)
group by T1.user2_id
order by maxDate desc) T2
join chat on (T2.maxDate = chat.msg_time) ORDER BY T2.maxDate DESC";

Alternative to GROUP_CONCAT? Multiple joins to same table, different columns

I'm not even sure of the correct terminology here. MySQL newbie, more or less.
Given a couple tables defined as follows:
CREATE TABLE users
( user_id int(11) NOT NULL auto_increment
, name VARCHAR(255)
, pri_location_id mediumint(8)
, sec_location_id mediumint(8)
, PRIMARY KEY (user_id)
);
CREATE TABLE locations
( location_id mediumint(8) NOT NULL AUTO_INCREMENT
, name varchar(255)
, PRIMARY KEY (location_id)
)
I'm trying to do a query to get the user name and both primary and secondary locations in one go.
I can get one like this:
SELECT u.name AS user_name, l.name as primary_location FROM users u, locations l WHERE u.primary_location_id=l.location_id
But I'm drawing a total blank on the correct syntax to use to get both in one query.
SELECT u.name AS user_name, l1.name as primary_location , l2.name as secondary_location
FROM users u
JOIN locations l1 ON(u.pri_location_id=l1.location_id)
JOIN locations l2 ON(u.sec_location_id = l2.location_id);
First of, I would strongly consider changing your DB schema if allowable to add a users_locations table that can be used to properly describe this many to many relationship.
This table could look like:
user_id location_id location_type
1 1 primary
1 2 secondary
2 1 secondary
2 2 primary
and so forth.
You would likely want a compound primary key across all three columns. And location_type might best be enum data type.
Your query would then be like
SELECT
u.name AS user_name
l.name AS location_name
ul.location_type AS location_type
FROM users AS u
INNER JOIN user_location AS ul /* possibly use left join here if user can exist without a location */
ON u.user_id = ul.user_id
INNER JOIN locations AS l
ON ul.location_id = l.location_id
ORDER BY ul.location_type ASC
This would return up to two records per user (separate record for primary and secondary, primary listed first)
If you need this collapsed to a single record you could do this:
SELECT
u.name AS user_name
COALESCE(CASE WHEN ul.location_type = 'primary' THEN l.name ELSE NULL END CASE) AS primary_location,
COALESCE(CASE WHEN ul.location_type = 'secondary' THEN l.name ELSE NULL END CASE) AS secondary_location
FROM users AS u
INNER JOIN user_location AS ul /* possibly use left join here if user can exist without a location */
ON u.user_id = ul.user_id
INNER JOIN locations AS l
ON ul.location_id = l.location_id
GROUP BY `user_name`
If however you are stuck with current schema, then solution by #Jlil should work for you.

SQL SELECT QUERY

i have 3 tables:
users:
uid int(11) - userid(primary key, auto_increment)
name varchar(255)
pass varchar(64)
created int(11)
projects:
pid int(11) .....
name varchar(150)
description varchar(255)
created int(11)
users_projects:
uid int(11) - user id
pid int(11) - product id
What is the query for: showing the projects(name and description) sorted by name for the user with a certain name?
This is what i've got so far:
SEECT name,description FROM projects ORDER BY name ASC
SELECT a.*, b.*
FROM users a
INNER JOIN users_projects b
ON a.uid = b.uid
INNER JOIN projects c
ON b.pid = c.pid
ORDER BY a.Name ASC
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
Looks like you just need to join up the tables. Here #Name is a parameter containing the user's name you want project details for:
SELECT projects.Name,
projects.Description
FROM projects
INNER JOIN users_projects
ON projects.pid = users_projects.pid
INNER JOIN Users
ON users_projects.UId = Users.UId
WHERE Users.Name = #Name
ORDER BY projects.Name ASC