SQL Code to order by data from related table - mysql

Okay this SQL query is giving me a headache, hoping theres someone who's done something like this before.
I have two tables (truncated)
tblTickets: tblNotes:
ticketno (int) noteid (int)
firmid (int) ticketno (int)
ticket_desc (text) datecreated (datetime)
... ...
They are related in that a Ticket can have many Notes
What I need to do is create a query that searches by firmid (i.e. 32) and orders the "Tickets" by their latest "Note" using tblNotes.datecreated (ordered newest first)
Thanks!
NB. MySQL server (5.5.32)
EDIT: To those who've marked the question down: I have tried, and the furthest successful SQL I got was to list all tickets and notes joined by using JOIN on ticketno, I didnt add this code to the question because I guessed I was going about it all the wrong way, and maybe I needed to use a UNION, something I've always found tricky to use.
I need it to only search by the latest note for each ticket. Thats what I needed help on.

You need to use a sub-query within the WHERE clause of your SQL to identify the last note date and then join to the SQ to limit the notes that are returned.
The following should be enought to get you started.
SELECT ...
FROM tblTickets T
INNER JOIN
tblNotes N
ON N.ticketno = T.ticketno
INNER JOIN
(SELECT N1.ticketno
,MAX(N1.datecreated) AS last_note_date
FROM tblNotes N1
GROUP BY
N1.ticketno
)SQ
ON N.ticketno = SQ.ticketno
AND N.datecreated = SQ.last_note_date

Related

mysql left join and order by

hi i have to different tables m_mp and m_answer
both have m_date and m_mdate which fills with time() function i want to select both entries but order by date
example:
first table: 'some text','6464647776'
second table 'some answer','545454545'
so i want to show first second table and then the first one
this is the code im using:
SELECT r.*,u.*
FROM `mensajes` as r
LEFT JOIN `m_answer` as u on r.id = u.id_m
WHERE r.id = '1'
ORDER BY m_date
and then display the result of each table using while-loop
I guess I get what you want to do.
You may force both grouping and ordering using ORDER BY, like this:
http://sqlfiddle.com/#!9/373d65/9
I know the solution is not optimal in terms of speed, but, given proper indices, I suspect performance to be acceptable, unless you are already aiming for millions of messages; when that time comes, you would like to either properly GROUPBY, or make subsequent queries for just the recently answered questions from the current page.

Remove duplicates from LEFT JOIN query

I am using the following JOIN statement:
SELECT *
FROM students2014
JOIN notes2014 ON (students2014.Student = notes2014.NoteStudent)
WHERE students2014.Consultant='$Consultant'
ORDER BY students2014.LastName
to retrieve a list of students (students2014) and corresponding notes for each student stored in (notes2014).
Each student has multiple notes within the notes2014 table and each note has an ID that corresponds with each student's unique ID. The above statement is returning a the list of students but duplicating every student that has more than one note. I only want to display the latest note for each student (which is determined by the highest note ID).
Is this possible?
You need another join based on the MAX noteId you got from your select.
Something like this should do it (not tested; next time I'd recommed you to paste a link to http://sqlfiddle.com/ with your table structure and some sample data.
SELECT *
FROM students s
LEFT JOIN (
SELECT MAX(NoteId) max_id, NoteStudent
FROM notes
GROUP BY NoteStudent
) aux ON aux.NoteStudent = s.Student
LEFT JOIN notes n2 ON aux.max_id = n2.NoteId
If I may say so, the fact that a table is called students2014 is a big code smell. You'd be much better off with a students table and a year field, for many reasons (just a couple: you won't need to change your DB structure every year, querying across years is much, much easier, etc, etc). Perhaps you "inherited" this, but I thought I'd mention it.
GROUP the query by studentId and select the MAX of the noteId
Try :
SELECT
students2014.Student,
IFNULL(MAX(NoteId),0)
FROM students2014
LEFT JOIN notes2014 ON (students2014.Student = notes2014.NoteStudent)
WHERE students2014.Consultant='$Consultant'
GROUP BY students2014.Student
ORDER BY students2014.LastName

MySQL Select Newest Approval Date among article date & comment date

My aim is to write the last modified date (lastmod) of my approved articles for my sitemap.xml file. There are 2 possibilities for this data.
If article has no approved comment, then lastmod is the approval
date of the article.
If article has at least 1 approved comment, then lastmod is the
approval date of the last approved comment of related article.
after asking php unsuccessful while loop within prepared statements question and reading answers, I decided
not to use loop within prepared for this case
add col_article_id column to my comments table which shows the
related article's id in article table
and try to solve my case with a smarter mySQL query
I have 2 tables:
articles
comments (comments.col_article_id links the comment to the related
article)
After I tried query below,
select tb_articles.col_approvaldate, tb_comments.col_approvaldate
from tb_articles, tb_comments
where tb_articles.col_status ='approved' AND tb_comments.col_status ='approved' AND tb_articles.col_id=tb_comments.col_article_id
my problems are:
1 - I need someway as if it was allowed in mysql syntax that select max( tb_articles.col_approvaldate, tb_comments.col_approvaldate)
2 - If I have n approved articles without any approved comment and m approved articles with approved comment(s), then I should have n+m result rows with 1 column at each row. But currently, I have m rows with 2 columns at each row.
So I'm aware that I'm terribly on wrong way.
I also searched "mysql newest row per group" keywords. But this the point I could arrived after all.
this is my 1st join experience. can you please correct me? best regards
Try this:
select
tb_articles.id,
ifnull(
max( tb_comments.col_approvaldate),
tb_articles.col_approvaldate
) as last_approved
from tb_articles
left join tb_comments
on tb_articles.col_id=tb_comments.col_article_id
and tb_comments.col_status ='approved'
where tb_articles.col_status ='approved'
group by 1;
Do I understand correctly that tb_comments record for an article is created by default? This should not be the case - if there are no comments, there shouldn't be a record there. If there is, what is the default date you are putting in? NULL? Also tb_comments.col_status seems redundant to me - if you have tb_comments.col_approvaldate then it is approved on that date and you don't really need status at all.
This query is probably what would work for you (commented AND shouldn't change things if I understand your table structure properly):
SELECT
a.col_id AS 'article_id',
IFNULL(MAX(c.col_approvaldate), a.col_approvaldate)
FROM
tb_articles a
LEFT JOIN tb_comments c ON a.col_id = c.col_article_id #AND c.col_status ='approved'
WHERE
a.col_status ='approved'
GROUP BY a.col_id

Copy MySQL table and populate with additional fields

I want to copy an existing MySQL table over to a duplicate table, but with two additional fields populated by data retrieved from other queries. It's for a forums software that never captured the original creation date of the thread (it always overwrote the time with the most recent reply).
So I want to take the existing table, 'threads'
thread_id
thread_author
thread_subject
thread_last_reply_date
and create a new table, 'new_threads' of the same structure, but with two extra fields:
thread_id
thread_author
thread_subject
thread_last_reply_date
thread_creation_date
thread_last_poster_id
Both thread_last_reply_date and thread_last_poster_id could be populated from dependent queries.. For example, last_poster_id with a query of:
SELECT post_author FROM posts WHERE thread_id = ? AND post_date = thread_last_reply_date
And for the thread_creation_date:
SELECT MIN(post_date) FROM posts WHERE thread_id = ?
That's essentially the process I would do with a PHP script.. A series of SELECTs and then inserting records one by one. Any advice or direction on how to do this type of process in pure SQL would be crazy helpful (if it's possible).
EDIT: an example of the technique would be helpful. I don't need an exact answer for the above. I'm sure everyone has better things to do.
Just had a similar problem.
This solution worked for me:
INSERT INTO `new_thread` SELECT *,null,null FROM `thread` WHERE 1=1
To create your target table (empty):
CREATE TABLE new_threads
SELECT t.*, thread_creation_date date, thread_last_poster_id number
FROM thread where 1=0;
and to populate it:
insert into new_threads(thread_id, thread_author, thread_subject, thread_last_reply_date, thread_creation_date, thread_last_poster_id)
(select t.*,
min(p.post_date),
(SELECT p1.post_author
FROM posts p1
WHERE p1.thread_id = t.thread_id
AND p1.post_date = t.thread_last_reply_date) thread_last_poster_id
from threads t, posts p
where t.thread_id = p.thread_id;
(untested)

Subquery or a double query?

For a client I have built a travelagency website. Now they asked me to optimize and automize some things. One of these things is that the accommodations shown in the searchlist must be bookable.
Simplified this is the structure
I have an AccommodationObject, an Accommodation has 1 or more PricePeriods.
What I need to do pick out the last priceperiod connected to a given accommodation. The priceperiod has a field 'date_until', which is a timestamp. In the query a check must be made, current timestamp must be less than the last timestamp from a priceperiod.
This is easy to do with a second query which just gets the last timestamp from the priceperiod table from all the priceperiod-rows connected to the given accommodation.
I'm wondering if this is the best case, or if I should use a subquery for this. And if so, how would a query like this look? I don't have much experience with subqueries.
Update
Table structure (simple)
Accommodation ->ID
PricePeriod -> ID | AccommodationID | DateUntil
Simplified:
SELECT fieldlist FROM Accommodation WHERE ID = $id
SELECT MAX(DateUntil) FROM PricePeriod WHERE AccommodationID = $id
But I would like to this in one query. I hope it's clear this way..
It depends upon a number of things, but what you should do is try a few different alternatives.
Personally, I would do:
SELECT fieldlist,
(SELECT MAX(DateUntil) FROM PricePeriod) WHERE AccomidationID = a.id) AS last_date
FROM Accommodation AS a
WHERE a.id = $id
You could also do (But it may not be as efficient)...:
SELECT fieldlist, MAX(b.DateUntil)
FROM Accommodation AS a
JOIN PricePeriod AS b ON a.id = b.AccommodationID
WHERE a.id = $id
GROUP BY a.id
The big thing is to try them all (Be sure to use SQL_NO_CACHE so that the results are true each time). Run them through EXPLAIN to try to see how "heavy" they are...