I have 2 tables: user and comment.
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)
);
And I want my output like the following:
I want to find recent comment from the database:
However, I tried like this and cannot get my output:
select u.userID, c.commentID, u.userCreateDate
from comment c
left join userID u on c.userID = s.userID
order by u.userCreateDate desc
How should I modify so that I can get my output?
You don't want to order it by the userCreateDate from the user table, because that will be the same for all comments. It would have been nice for you to have a commentCreateDate but since you don't have that you can order it by the commentID.
Change
order by u.userCreateDate desc
to
order by c.commentID desc
Edited to add:
You also need to change your select to get the actual comment.
select u.userID, c.commentID, u.userCreateDate
should be
select u.userID, c.commentID, c.comment, u.userCreateDate
to get your desired output. Plus I don't think you want to include userCreateDate in the output as people could confuse that with the date the comment was written.
Related
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');
I'm facing MySQL query problem with ordering grouped rows.
Tables:
statuses (
id int primary key auto_increment,
name varchar(30)
);
orders (
id int primary key auto_increment,
order_code varchar(10),
order_date timestamp default current_timestamp,
user_id int -- fk to users
);
orders_statuses (
id int primary key auto_increment,
status_changed timestamp default current_timestamp,
order_id int, -- fk to orders(id)
status_id int -- fk to orders(id)
);
Now, I need to join them in ONE query (this is important due to database object limitation with my PHP software - no sub-queries allowed, not even union) and get all possible orders, but only the latest status change as current status.
Statuses from status table may be inserted randomly - there is no way to use max function on status_id field where order_id (currently id 1 is new, 2 is canceled, 4 is paid etc.).
Grouping by order_id (id in orders or order_code) always returns first available status inserted into orders_statuses, even if ordered by date.
I've also tried using having status_changed=max(status_changed), but it won't work.
So my question is:
How should I group them by order_id to get last, not first status name available for each row?
// edit
Here is the code I'm trying to move from my Workbench to PHP DB Object:
select
(select l.name from statuses l where l.id = (select t.status_id from orders_statuses t where t.order_id = oh.id order by t.status_changed desc limit 1)) as status,
oh.order_code,
oh.id,
oh.order_total,
su.name as order_user,
oh.order_date as ordered,
max(os.status_changed) as updated,
oh.id as uid
from orders oh
left join orders_statuses os on (oh.id = os.order_id)
left join users su on (oh.shop_user_id = su.id)
group by
oh.id
order by
oh.order_date desc,
os.created desc
So basically I need simpler query to understand it and put it into $this->db->use('table', on condition)->...->select(array(fields))
// edit
After hours of thinking I can tell I'm lacking know-how. This problem can be solved by using
SELECT
status_id,
created,
order_id
FROM
orders_statuses
GROUP BY
order_id,
status_id
ORDER BY
created DESC;
and transforming it to return just one status_id for each order_id with max created within single order_id group - this is where I need your help.
I need to create a sql that contains a list of users, and for each user the number they have
reviewed.
I tried this, but it didnt give the desired output because i didnt know how to work the SUM into it.
SELECT review.revID, reviewer.name FROM review , reviewer WHERE review.revID = reviewer.revID
Any assistance would be apprectiated
here are my tables
CREATE TABLE reviewer (
revID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(40),
email VARCHAR(40),
password VARCHAR(125)
);
CREATE TABLE movie (
movID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(30),
release_date date
);
CREATE TABLE review (
revID INT,
movID INT,
rating INT CHECK (rating > 0 AND rating < 10) ,
review_date datetime(6),
comment VARCHAR (300),
helpful INT,
PRIMARY KEY (revID,movID),
FOREIGN KEY (revID)
REFERENCES reviewer(revID),
FOREIGN KEY (movID)
REFERENCES movie(movID)
);
Try this query:
SELECT
count(movId) AS Total_Movie_Count,
r.name AS Reviewer_Name,
r.revId as Reviewer_Id
FROM review
INNER JOIN reviewer r on r.revId = review.revId
GROUP BY review.revId
You have to use GROUP BY for aggregated column movId. And to get the reviewer name, you have to INNER JOIN with revId.
Select count(*) as no, revId from review
Group by revId
You can use the above query
Try to use explicit join syntax (e.g. inner join, left join, cross join). Because the relationships among different tables are better explained using explicit join syntax.
SELECT
review.revID,
reviewer.name,
SUM(rating) As totalReview
FROM review
INNER JOIN reviewer ON review.revID = reviewer.revID
GROUP BY reviewer.revID;
Note: You need to use GROUP BY revID in order to get output for each reviewer.
And using aggregate function SUM along with group by will provide total rating / review for each reviewer.
Btw, MYSQL doesn't support CHECK constraint.
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)
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";