sort rows based on fields from two different tables - php

I have two tables as follows:
Table 1 (t1)
______________________________________________________________________________________________
RequestId | Raised_By | CommentDate | Comment | AttachmentName | Attachment | AttachmentSize |
----------+-----------+-------------+---------+----------------+------------+----------------+
Table 2 (t2)
______________________________________________
RequestId | CommentDate | Comment | Raised_By |
----------+-------------+---------+-----------+
Note: CommentDate is a timestamp
I want to select the only one record i.e comment from table t1 or t2, whose RequestId=RequestId and the CommentDate is the latest.
My query is as follows:
(SELECT Comment from t1 WHERE RequestId = "."\"".$_POST['RequestId']."\" and Raised_By="."\"".$_POST['Raised_By']."\" and CommentDate="."\"".$_POST['CommentDate']."\")
UNION
(SELECT Comment from t2 WHERE RequestId = "."\"".$_POST['RequestId']."\" and Raised_By="."\"".$_POST['Raised_By']."\" )
ORDER BY CommentDate DESC
LIMIT 1
But I am getting an error saying unknown column CommentDate.

Can you ORDER BY if you have not SELECTED that ?
We need to understand the sequence in which query executes. Unless you select the field 'CommentDate' you cannot arrange in order.
Try to select the 'CommentDate' along with 'Comment' and check
(SELECT Comment, CommentDate from t1 WHERE RequestId = "."\"".$_POST['RequestId']."\" and Raised_By="."\"".$_POST['Raised_By']."\" and CommentDate="."\"".$_POST['CommentDate']."\")
UNION
(SELECT Comment, CommentDate from t2 WHERE RequestId = "."\"".$_POST['RequestId']."\" and Raised_By="."\"".$_POST['Raised_By']."\" )
ORDER BY CommentDate DESC
LIMIT 1

Why use UNION when you can JOIN both tables?
SELECT t1.Comment,
CASE WHEN t1.CommetDate > t2.CommentDate
THEN t1.commentDate
ELSE t2.commentDate
END AS commentDate
FROM t1 INNER JOIN t2 ON t1.RequestId = t2.RequestId
ORDER BY commentDate DESC
LIMIT 1

Related

MySQL joining tables and returning the latest row from the second table when the comparison is made between identical values

I have table 1: users
id | name |
1 | john |
2 | garry|
3 | sam |
And table two called posts:
id | user_id | title | posted
1 | 1 | Something | 1551128761
2 | 1 | Else | 1551128761
3 | 3 | Some Title | 1551122745
4 | 2 | Demo Title | 1551129777
5 | 3 | Something | 1551126793
user_id in the second table is the id of the user in the first table
I need to get the latest post out of the table and i'm doing that currently by using this query:
SELECT u.id, u.name, p.title
FROM users AS u
LEFT JOIN posts AS p
ON p.user_id= u.id
WHERE p.posted = ( SELECT MAX(posted) FROM posts WHERE user_id = u.id )
ORDER BY u.id
LIMIT 15
But the problem with this query is that if the timestamp is the same for the same user (in this example for user with user_id 1 the timestamp is the same) i'm getting both of those rows instead of just the latest one(the latest one has the highest id)
Try this MySQL query:
SELECT u.id,
u.name,
p.title
FROM users AS u
JOIN posts AS p
ON p.id = (SELECT pi.id
FROM posts AS pi
WHERE pi.user_id = u.id
ORDER BY pi.id DESC
LIMIT 1);
Tested and works fine. Here is a demo: DBFiddle
To speed up select query, consider adding indexes
ALTER TABLE posts ADD INDEX(user_id);
ALTER TABLE posts ADD INDEX(posted);
One option using id column from posts table as following. This is assuming id is going to be different for each post record is posts table. Demo here
SELECT u.id, u.name, p.title,p.posted
FROM users AS u
LEFT JOIN posts AS p
ON p.user_id= u.id
WHERE (p.posted,p.id) = ( SELECT MAX(posted),MAX(id) FROM posts WHERE user_id = u.id )
ORDER BY u.id
How about restructuring the query slightly?
SELECT posts.title, users.id, users.name
FROM posts, users
WHERE posts.user_id = users.id
ORDER BY posts.posted DESC, posts.id DESC
LIMIT 1
Essentially selecting from posts, ordering by the posted timestamp and secondly the id of the post in descending order in case timestamp is the same.

get number of rows in join query

I am saving Item and order in different tables. i want to count order as per item.
Here is my table structure.
Table1: Order table
id | table2_id
1 | 1
2 | 1
3 | 2
4 | 2
Table2: Item Table
id | user_id
1 | 1
2 | 2
3 | 1
4 | 2
One item has multiple order as shown in the table structure. Now i want to count the order as each item.
I have tried using join but it gives me all row cont: 4
SELECT count(Table1.id) as order_count_for_each_item
FROM `Table2` as `t2`
LEFT OUTER JOIN `Table1` as `t2` ON `t1`.`id` = `t2`.`table2_id`;
But i want each item count: as For Item1 is: 2 and Item2 is: 2
The conclusion:
As Rahul Suggested this:
SELECT count(*) as order_count_for_each_item
FROM `Table2` as t2
LEFT OUTER JOIN `Table1` as t1 ON `t1`.`table2_id` = `t2`.id
GROUP BY t1.`table2_id`
This query give the me result which i want initially.
order_count_for_each_item
1 |
2 |
But the answer i accepted (Bibhudatta Sahoo) gives me the item count which is zero and also the count of item par order.
SELECT t2.`id`,
(SELECT count(t1.id) form `Table1` as t1
where t2.`id` = t1.`table2_id`) as order_count_for_each_item
FROM `Table2` as t2
group by t2.`id`
order by t2.`id` asc
Item ID | order_count_for_each_item
1 | 2
2 | 2
3 | 0
4 | 0
So I accepted that answer.
Try Like this
SELECT t2.`id`,
(SELECT count(t1.id) form `Table1` as t1
where t2.`id` = t1.`table2_id`) as order_count_for_each_item
FROM `Table2` as t2
group by t2.`id`
order by t2.`id` asc
You are missing a group by here
SELECT count(*) as order_count_for_each_item
FROM `Table2` as t2
LEFT OUTER JOIN `Table1` as t1 ON `t1`.`table2_id` = `t2`.id
GROUP BY t1.`table2_id`
You will have to use an aggregate function Group by. group your data over the item and get the count.
SELECT item.id,ifnull(count(order.id),0) as order_count_for_each_item
FROM `Table2` as `item`
LEFT JOIN `Table1` as `order` ON order.table2_id=item.id
group by item.id ;

MYSQL : select count with union three table

I have three table content information about posts
and each table has Post_id it's foreign_key for Post table
first table = `likes`
second table = `Comment`
and last one = `Visitor`
each Table has some info about users like session or id and etc
i need to create new view table contain post id and the number of visitor , likes , comment
i tried this
SELECT *
from (
select id , count(id) as Comment
from Post left join Comment on id = Post_id
group by id
UNION
select id, count(id) as Visitor
from Post left join Visitor on id = Post_id
group by id
UNION
select id, count(id) as Likes
from Post left join Likes on id = Post_id
group by id
) CountsTable
GROUP BY CountsTable.id
but it didnt work .
i dont know why the result is only the first inner select
in my example the result is
| id | Comment|
|--------|------- |
| 1 | 55 |
| 2 | 25 |
| 3 | 12 |
i expect something like that
| id | Comment | Likes | Visitor |
|--------------|-------|---------|
| 1 | 55 | 100 | 2000 |
No need to use UNION. Count the records for each post in all three tables and Left Join result with Post table
Try something like this
SELECT id,
comments,
vistors,
likes
FROM Post p
LEFT JOIN (SELECT Count(Post_id) comments, Post_id
FROM Comment
GROUP BY Post_id) c
ON p.id = c.Post_id
LEFT JOIN (SELECT Count(Post_id) vistors, Post_id
FROM Visitor
GROUP BY Post_id) v
ON p.id = v.Post_id
LEFT JOIN (SELECT Count(Post_id) likes, Post_id
FROM Likes
GROUP BY Post_id) l
ON p.id = l.Post_id
You can do it with a Left Join query, e.g.:
select u.id, count(distinct l.id) as likes, count(distinct c.id) as comments
from user u left join likes l on u.id = l.user_id
left join comments c on u.id = c.user_id
group by u.id;
Here is SQL Fiddle.
SELECT id, SUM(Comment),SUM(Visitor),SUM(Likes) from (
select id , count(id) as Comment, 0 as Visitor, 0 as Likes
from Post left join Comment on id = Post_id
group by id
UNION ALL
select id, 0 as Comment, count(id) as Visitor , 0 as Likes
from Post left join Visitor on id = Post_id
group by id
UNION ALL
select id, 0 as Comment, 0 as Visitor, count(id) as Likes
from Post left join Likes on id = Post_id
group by id
) CountsTable
GROUP BY CountsTable.id

Slow query using "where in" and "order by select count"

I want to show post from users that specified user is followed and i have two tables at below. but its query is very slow.
table user
id | username
1 | name1
2 | name2
3 | name3
..
..
table post
id | poster_id | post_content
1 | 2
2 | 3
3 | 10
..
..
table follow
followerid | followtoid
1 | 2
1 | 3
2 | 10
..
..
Assume that all tables have more than 1000 rows.
This's SQL
SELECT *
FROM post
WHERE poster_id IN (
SELECT followtoid
WHERE followerid = $_SESSION['userid']
)
And this's the second cast is very slow too.
I want to list all member by order from their total posts.
SELECT *
FROM user
ORDER BY (
SELECT COUNT(id)
FROM post
WHERE post_id = user.id
) DESC;
Try indexing post.userid, post.poster_id, followtoid.followerid and user.user_id, using CREATE INDEX, and use LEFT JOIN clause on your queries instead:
SELECT *
FROM user u
LEFT JOIN SELECT poster_id, COUNT(*) as count FROM post p GROUP BY poster_id
ON (u.user_id = p.poster_id)
ORDER BY count DESC;
and:
SELECT * FROM post AS p
LEFT JOIN (SELECT followerid FROM followtoid) AS f
ON (p.userid=f.followerid)
WHERE p.userid = {$_SESSION['userid']}
Use a JOIN for the first query
SELECT p.*
FROM post p
JOIN follow f ON p.post_id = f.followtoid
WHERE f.followerid = $_SESSION['userid']
and a JOIN plus a GROUP BY for the second
SELECT u.*, tbl.postCount
FROM user u
JOIN (
SELECT poster_id, COUNT(*) AS postCount
FROM post p
GROUP BY posterID
) tbl ON tbl.poster_id = u.id
ORDER BY postCount DESC
You can accomplish the second query without a subquery:
SELECT u.*, COUNT(p.poster_id) as postCount
FROM user u
LEFT JOIN post p
ON (u.user_id = p.poster_id)
GROUP BY u.user_id
ORDER BY postCount DESC;

Mysql query ( LINK tickets, employee , cats , comments ) using JOIN

here is my tables
Tickets
tic_id,
tic_cat
tic_priority
tic_cus
tic_date
tic_title
tic_msg
tic_files
tic_emp
tic_moved
tic_statue
tic_rate
Employee
emp_id
emp_name
emp_username
emp_password
emp_cat
emp_special
emp_lastlogin
emp_session
emp_code
emp_statue
emp_master
emp_ip
Cats
cat_id
cat_type
cat_name
cat_statue
cat_delete
cat_date
cat_ip
cat_options
Comments
com_id
tic_id
cus_id
emp_id
com_msg
com_time
com_ip
com_statue
And I need the result as
tic_id | tic_cat | cat_name | tic_title | tic_statue | tic_priority | tic_msg | emp_name | comments_row | last_comment |
I Make this query but i have 2 problems
Query Is
SELECT
tickets.tic_id
,tickets.tic_cat
,cats.cat_name
,tickets.tic_title
,tic_statue
,tic_priority
,tickets.tic_msg
,employee.emp_name
,count(comments.com_id)
,( SELECT comments.com_msg
from comments
order by com_id DESC limit 1 )
AS last_comment
FROM tickets
LEFT JOIN employee
on (tickets.tic_emp = employee.emp_id)
LEFT join cats
on (tickets.tic_cat = cats.cat_id)
LEFT JOIN comments
on(tickets.tic_id = comments.tic_id)
WHERE tic_cus=2 /* 2 -> This Is Customer Id */
GROUP BY comments.tic_id
My Problems Is
i have 3 Result In Database To Customer Number 2 -> only show 2 results
i want to get Last Comment -> the 2 Result have the same last comment
How Can i do this Query With Out This 2 Errors
Edit The Post After New Query
Problem number Two Solved Using This Query
SELECT
tickets.tic_id
,tickets.tic_cat
,cats.cat_name
,tickets.tic_title
,tic_statue
,tic_priority
,tickets.tic_msg
,employee.emp_name
,count(comments.com_id)
,( SELECT comments.com_msg
from comments
WHERE tickets.tic_id = comments.tic_id
order by com_id DESC limit 1 )
AS last_comment
FROM tickets
LEFT JOIN employee
on (tickets.tic_emp = employee.emp_id)
LEFT join cats
on (tickets.tic_cat = cats.cat_id)
LEFT JOIN comments
on(tickets.tic_id = comments.tic_id)
WHERE tic_cus=2
GROUP BY comments.tic_id
Solved
SELECT
tickets.tic_id
,tickets.tic_cat
,cats.cat_name
,tickets.tic_title
,tic_statue
,tic_priority
,tickets.tic_msg
,employee.emp_name
,count(comments.com_id)
,( SELECT comments.com_msg
from comments
WHERE tickets.tic_id = comments.tic_id
order by com_id DESC limit 1 )
AS last_comment
FROM tickets
LEFT JOIN employee
on (tickets.tic_emp = employee.emp_id)
LEFT join cats
on (tickets.tic_cat = cats.cat_id)
LEFT JOIN comments
on(tickets.tic_id = comments.tic_id)
WHERE tic_cus=2
GROUP BY tickets.tic_id
1) Can you show some data in these tables to demonstrate? In other words, how do you know you should have three records? Does select * from tickets where tic_cus = 2 by itself return 3 records?
2) You need to filter the comments subquery by ticket. I would also recommend having the comment count in a subquery as well and leave out the GROUP BY altogether:
,( select count(comments.com_id)
from comments
where comments.tic_id = tickets.tic_id) as comment_count
,( select comments.com_msg
from comments
where comments.tic_id = tickets.tic_id
^^^^^^^ filter by ticket so not last of ALL comments
order by com_id DESC limit 1) as last_comment

Categories