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

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

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.

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

sort rows based on fields from two different tables

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

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;

Display only the newest record for each row in MySQL db using PHP

I have two tables of which one is updated daily. I would like to display "only" the latest record for each row.
This is the query I am using now that of course returns all the records.
SELECT *
FROM ss_pumps, secondary_systems WHERE ss_pumps.id=secondary_systems.segment_id
ORDER BY id ASC
Any help would be greatly appreciated!
You can find the latest record for every segment_id by ID using subquery. The result of the subquery is then join against the two tables: ss_pumps and secondary_systems.
SELECT a.*, c.*
FROM ss_pumps a
INNER JOIN
(
SELECT segment_id, MAX(datefield) max_val
FROM secondary_systems
GROUP BY segment_id
)b ON a.id = b.segment_id
INNER JOIN secondary_systems c
ON b.segment_id = c.segment_id AND
b.max_val = c.datefield
Actually, I'm not sure how your tables: ss_pumps and secondary_systems are related with each other.
I think you want it the other ways,
SELECT a.*, b.*
FROM secondary_systems a
INNER JOIN ss_pumps b
ON a.segment_ID = b.segment
INNER JOIN
(
SELECT segment, MAX(ID) max_val
FROM ss_pumps
GROUP BY segment
) c ON b.segment = c.segment AND
b.ID = c.max_val
Use this query:
SELECT * FROM ss_pumps, secondary_systems WHERE ss_pumps.id=secondary_systems.segment_id ORDER BY id DESC LIMIT 1
This is assuming that id is an auto increment column and will always be inserted in order.
Here's what I got:
SELECT *
FROM
ss_pumps ssp
LEFT JOIN ( SELECT * FROM secondary_systems ORDER BY id DESC ) ss ON ( ssp.id = ss.segment_id )
GROUP BY
ssp.id
ORDER BY
ssp.id ASC
CAVEAT: I'm assuming that the secondary_systems has its own id field that also autoincrements. That's the only way you can make sure you're getting "only" the latest record for each row.
Demo: http://sqlfiddle.com/#!2/f816b/2/0
In my demo ss_pumps held the parents while secondary_systems held the children. Each parent has 3 children. All but the last children are boys. The last child is always a girl. According to your problem, the resulting query should yield only girls.
| ID | PARENT | SEGMENT_ID | CHILD |
------------------------------------
| 1 | mother | 1 | betty |
| 2 | father | 2 | tina |

Categories