php mysql - select most recent data from two tables - mysql

I have searched this site and others but cannot find any help with this problem. Maybe I am making this more difficult than necessary.
I have two tables as follows. I want to return all the information for each item but only the most recent data and include data from both tables
table 1: serviceRequestSubmission
sid customerID
1001 11111
1002 22222
1003 33333
1004 44444
1005 55555
table 2: serviceRequestHistory
historyID requestID statusUpdate
1 1001 Assigned
2 1002 Assigned
3 1003 Pending
4 1004 Delayed
5 1002 Pending
6 1002 Closed
I want to return:
sidID historyID statusUpdate
1001 1 Assigned
1002 6 Closed
1003 3 Pending
1004 4 Delayed
1005 - Submitted
I have tried the following code but it returns all the rows of data but I only want the most recent/highest historyID.
SELECT serviceRequestSubmissions.*, serviceRequestHistory.*
FROM serviceRequestSubmissions
LEFT JOIN serviceRequestHistory ON serviceRequestSubmissions.sid = serviceRequestHistory.requestID
ORDER BY serviceRequestSubmissions.sid DESC
Any help would be appreciated.
Thank you!

SELECT serviceRequestSubmissions.*, serviceRequestHistory.*
FROM serviceRequestSubmissions
LEFT JOIN serviceRequestHistory
ON serviceRequestSubmissions.sid = serviceRequestHistory.requestID
AND historyID IN (
SELECT max(historyID)
FROM serviceRequestHistory
GROUP BY requestID
)
ORDER BY serviceRequestSubmissions.sid DESC
EDIT:
Only closed:
SELECT serviceRequestSubmissions.*, serviceRequestHistory.*
FROM serviceRequestSubmissions
JOIN serviceRequestHistory
ON serviceRequestSubmissions.sid = serviceRequestHistory.requestID
AND historyID IN (
SELECT max(historyID)
FROM serviceRequestHistory
WHERE statusUpdate = 'Closed'
GROUP BY requestID
)
ORDER BY serviceRequestSubmissions.sid DESC

Add a LIMIT clause at the end of the query:
LIMIT 2

You can use TIMESTAMP or id in your database and fetch record which has greatest TIMESTAMP or id value or with descending TIMESTAMP or id order by LIMIT clause

This is a common problem of type greatest-n-per-group. I think this is the best way to solve it:
SELECT
s.sid sidID,
IFNULL(h1.historyID,'-') historyID,
IFNULL(h1.statusUpdate,'Submitted') statusUpdate
FROM
serviceRequestSubmissions s
LEFT JOIN serviceRequestHistory h1 ON ( s.sid = h1.requestID )
LEFT JOIN serviceRequestHistory h2 ON ( s.sid = h2.requestID AND ( h1.historyID < h2.historyID OR h1.historyID = h2.historyID AND h1.requestID < h2.requestID ) )
WHERE
h2.requestID IS NULL
ORDER BY
s.sid
This is how it works: given a row of the table serviceRequestHistory, there shouldn't be any other row with the same requestID and a greater historyID (the conditions after the OR is to solve the ties). This kind of solution is usually better than using sub-selects.

Related

SQL Server query for left join of two table

I have two tables, one is Table_Log for when user will update the data then it will stored one data into Table_Log, and another table is main registration table: Table_Registration and I need based on updatedDate of Table_Log data should come first order by desc.
Table_Log:
RegId Name updatedDate
-----------------------------------
3 jj 2018-03-21 13:30:04.497
3 jj 2018-03-20 13:30:04.497
Table_Registration
RegId Name Email SubDate
--------------------------------------------------------
2 kk kk#gmail.com 2018-03-01 15:30:04.497
3 jj jj#gmail.com 2018-02-26 15:30:04.497
1 Raj raj#gmail.com 2018-02-30 13:30:04.497
I need this output as my result:
RegId Name Email SubDate
--------------------------------------------------------
3 jj jj#gmail.com 2018-02-26 15:30:04.497
2 kk kk#gmail.com 2018-03-01 15:30:04.497
1 Raj raj#gmail.com 2018-02-30 13:30:04.497
I tried below query but some duplication is coming.
select r.*
from Table_Registration r
left join Table_Log a
on a.RegId = r.RegId
order by isnull(a.updatedDate, r.SubDate) desc
select r.*
from Table_Registration r
left join Table_Log a
on a.RegId = r.RegId
order by isnull(a.updatedDate, r.SubDate) desc
In the above code, you left join to Table Log. This will give you one row per row of tablelog, which is why you are getting duplication. You need to process table_Log in some way so that you are only getting the most recent row per registration, and then join to that. Something like this
select r.*
from Table_Registration r
left join (Select RegId, Max(updateDate) as updateDate from Table_Log Group By RegId) a
on a.RegId = r.RegId
order by isnull(a.updatedDate, r.SubDate) desc

mysql How to select an ID when it's values are equal to X

I have tried quite a lot of solutions and I decided to post it here to try and find a solution. Any little help is welcome (so I can learn too).
I have a table formed by ArticleID, UserID, and Votes (1/-1).
I want to select the ArticleID that contains a certain UserID and which SUM of Votes is equal to 1.
So far I arrived to:
SELECT catch.ID, votes.postid, catch.text, votes.userid, votes.value, catch.name FROM catch INNER JOIN votes ON catch.ID=votes.postid AND votes.userid=:iduser AND votes.value='1' ORDER BY ID DESC LIMIT 100
but this gives me an erroneous result, as it doesn't consider articles that have votes 1 and -1 (which SUM should be 0).
Thanks!
UPDATE
ID + Value + userid
1 | 1 | 54
1 | -1 | 54
3 | 1 | 54
7 | 1 | 56
7 | -1 | 56
Given the above table, and selecting just the user '54' the wanted result should be ID 3.
Is this what you want?
SELECT c.ID, v.postid, c.text, v.userid, v.value, c.name
FROM catch c INNER JOIN
votes v
ON c.ID = v.postid AND v.userid = :iduser
GROUP BY c.ID
HAVING SUM(v.value) = 1;
This is what you describe but it is a bit different from your query.
Try like this, but for :iduser set what particular id of user
SELECT catch.ID,
votes.postid,
catch.text,
votes.userid,
SUM(votes.value),
catch.name
FROM catch
LEFT JOIN votes ON catch.ID=votes.postid
WHERE votes.userid = :iduser and votes.value='1'
ORDER BY ID DESC
LIMIT 100

Calculate round(avg) from same table and join

I have two tables,
users
userid fname usertype
1 Steve vendor
2 Peter vendor
3 John normaluser
4 Mark normaluser
5 Kevin vendor
6 Alan vendor
7 Sean vendor
vendor_rating
id userid rating
1 1 4
2 2 3
3 2 2
4 2 4
5 1 3
6 5 2
7 5 2
userid is foreign key.
i want to show all vendors (only usertype vendor) from user table by descending/ascending average rating even if Vendor's rating is not available on table it should show, its information should display at last in descending, at first in ascending.
I want to fetch all users info from first table so i m using left join :
SELECT
users.name,
users.userid,
users.usertype
FROM users
LEFT JOIN (SELECT
ROUND(AVG(rating)) AS rating_avg,
userid
FROM vendor_rating
ORDER BY rating_avg DESC) ven
ON users.usertype = 'vendor'
AND users.userid = ven.userid
ORDER BY ven.rating_avg ASC;
Please help where am i going wrong.
EDIT:
I get this
userid ROUND(AVG(vr.ratings))
28 5
27 4
16 3
26 2
25 0
NULL NULL
NULL NULL
NULL NULL
NULL NULL
if i use
SELECT vr.userid, ROUND(AVG(vr.ratings)) FROM vendor_rating vr
RIGHT JOIN (SELECT users.fname, users.userid, users.usertype FROM users) u
ON u.id = vr.vendor_id WHERE u.usertype = 'vendor' GROUP BY vr.userid,u.fname
ORDER BY round(avg(vr.ratings)) ASC
i get NULL values from users table whose rating is not available in vendor_rating table those should display userids
Try to this
SELECT
vr.userid,
u.fname,
ROUND(AVG(vr.rating))
FROM vendor_rating vr
INNER JOIN users u
ON u.userid = vr.userid
WHERE u.usertype = 'vendor'
GROUP BY vr.userid,
u.fname
ORDER BY round(avg(vr.rating)) ASC
finally i got it
SELECT users.fname, users.userid,users.usertype
FROM users
LEFT JOIN (select ROUND(AVG (ratings)) AS rating_avg,userid FROM
vendor_rating group by userid order by rating_avg desc ) ven
ON users.id=userid
WHERE users.usertype='vendor'
order by rating_avg desc
Thank you all, for sharing views to get idea to solve my problem.

Mysql left join table not between dates

I have the following issue, I've got 3 tables the first one is called courses where I have
courses| id | start | end |
--------------------------------------
1 2012-10-12 | 2012-11-12 |
students| id | available_start | available_end |
-------------------------------------------------
1 2012-10-13 2012-11-11
2 2012-11-06 2012-11-08
students_to_courses | student_id | course_id |
-------------------------------------------------
1 1
So I'm trying to find which students are available for courses periods. So if the student is added to student_to_courses and dates are between the course dates I don't need it.
I've got the feeling that the query should be with a sub query but I really don't understand them. My query now is looking like this but doesn't work properly.
SELECT s.id
FROM (`students` s)
LEFT JOIN `student_to_course` s2c ON `s2c`.`student_id` = `s`.`id`
LEFT JOIN `courses` assigned_2_course ON `s2c`.`course_id` = `assigned_2_course`.`id`
LEFT JOIN `courses` c ON `c`.`id` = 1
WHERE
(
(s.available_start NOT BETWEEN assigned_2_course.start AND assigned_2_course.end
AND
s.aviailable_end NOT BETWEEN assigned_2_course.start AND assigned_2_course.end
) OR assigned_2_course.end IS NULL)
AND
`s`.`available_start` BETWEEN c.start AND c.end
AND `s`.`available_end` <= c.end
GROUP BY `s`.`id`
ORDER BY `s`.`id` desc
Here is http://sqlfiddle.com/#!2/49c11/1
now works, but doesn't remove the students which are assigned in other courses with same dates how you can see I'm trying to get available students for course 3 which starts 02-03 and ends 02-08, student 2 is in course 3 so is not shown, student 1 is in course 2 which starts 01-03 and ends 03-01 so shouldn't be available.
Any help will be appreciated.
I used your SQL fiddle (but added another student record) http://sqlfiddle.com/#!2/246645/1
try this to find all students that could attend course 3 because they are not in a class during that time:
SELECT student.*
FROM student
JOIN course
ON course.id = 3
AND student.available_start <= course.`start`
AND student.available_end >= course.`end`
WHERE NOT EXISTS
(SELECT *
FROM student_to_course
JOIN course AS c
ON student_to_course.course_id = c.id
WHERE student.id = student_to_course.student_id
AND (course.`start` BETWEEN c.`start` AND c.`end`
OR
course.`end` BETWEEN c.`start` AND c.`end`
OR
c.`start` BETWEEN course.`start` AND course.`end`));

Mysql 2 Tables join Limit Result return from both Table

I have been trying this requirement for few hours but im clueless as im not getting the desired result.
I have two table.
**Main Comment Table
----------------------------------------------------------------------------
id | comments | date_commented | comment_owner | commented_by
1 hello world ********** 321 123
Child Comment Table
----------------------------------------------------------------------------
id | mainpostID| child_comment_data | commented_by | date_commented**
1 1 child comment of hello world 456 ********
My requirement:
I want to retrieve the first 10 Main Comment along with Chilcomments for each Main comment. I will like to limit the number of Child comments to 5 for each Main comment.
What i tried:
SELECT maincomment.comments, childcomment.child_comment_data
FROM maincomment
LEFT JOIN childcomment ON maincomment.id = childcomment.mainpostID
AND maincomment.comment_owner = childcomment.commented_by
WHERE maincomment.id = childcomment.mainpostID
ORDER BY dateposted DESC
LIMIT 10
Results: Im getting only 10 Maincomments but the number of childcomments are just 1 for each Main comment. What i need is to return 5 childcomments for each of the Maincomment.
Will anyone please help out with some suggestions / query here.
Thanks alot.
You can use this solution:
SELECT a.*, b.*
FROM
(
SELECT *
FROM maincomment
ORDER BY dateposted DESC
LIMIT 10
) a
LEFT JOIN
(
SELECT a.*
FROM childcomment a
INNER JOIN childcomment b ON a.mainpostID = b.mainpostID AND a.id <= b.id
GROUP BY a.id
HAVING COUNT(1) <= 5
) b ON a.id = b.mainpostID
ORDER BY a.dateposted DESC, b.date_commented DESC
This gets the up to the 5 latest child-comments of the 10 latest main-comments. If there are no child-comments for a particular main-comment, the child-comment data will contain NULL values.