Pulling latest post from table - php

All,
I am trying to display the latest post from my authors.
The posts are in one table, the author in another. The queries used were: join on a column called content_id, and I am trying to work with MAX(item_date) which is the date the post was published.
Here are some queries I am running and the output, I seem to be getting everything except the latest posts from all authors:
First (and this bit is working) we need to get information about the author:
$query="SELECT content_id, title, source_image, url FROM content_detail where approved='y'";
$result1 = $mysqli->query($query) or die($mysqli->error.__LINE__);
// GOING THROUGH THE DATA
if($result1->num_rows > 0) {
while($fetch=mysqli_fetch_array($result1)) {
$title=$fetch['title'];
$feed_rss=$fetch['url'];
$content_id=$fetch['content_id'];
$source_image=$fetch['source_image'];
Now on that basis lets get the posts, round 1:
$query2 = "SELECT item_id, item_title, MAX(item_date) as item_date from posts WHERE content_id='$content_id' GROUP BY content_id";
$result2 = $mysqli->query($query2) or die($mysqli->error.__LINE__);
if($result2->num_rows > 0) {
while($rows2=mysqli_fetch_array($result2)) {
$item_id = $rows2['item_id'];
$item_title = $rows2['item_title'];
$item_date = $rows2['item_date']; `
This pulls back an in interesting set of results, the latest date of a post from an author, but not the latest title!
I have tried GROUP BY item_title and content_id to no avail.
The following pulls back just records that have more than one date in the database, the problem is (as this is new) some authors only have one post, these are not being displayed:
$query2 = "SELECT item_id, item_title, item_date FROM posts AS a WHERE content_id = content_id AND item_date = (
SELECT MAX(item_date)
FROM rssingest AS b
)
";
I have tried:
ORDER BY DATE DESC LIMIT 1
at the end of my queries to no avail.
item_date is a DATE type in the table.
Any help would be greatly appreciated!
Thanks,

You are running this query to get the maximum date:
SELECT item_id, item_title, MAX(item_date) as item_date
from posts
WHERE content_id = '$content_id'
GROUP BY content_id;
Of course you don't get the right item_title. It is not mentioned in the group by clause and has no aggregation function. So, you are using a MySQL extension (this query would fail in other databases).
You can get the most recent title using the substring_index()/group_concat() trick:
SELECT max(item_id),
substring_index(group_concat(item_title separator '|' order by item_date desc), '|', 1) as last_title,
MAX(item_date) as item_date
from posts
WHERE content_id = '$content_id'
GROUP BY content_id;
This will return one row. But, if there is only one row that you want, you can do:
SELECT p.*
from posts p
WHERE p.content_id = '$content_id'
ORDER BY item_date desc
LIMIT 1;
The previous version will generalize if you add a group by statement.

You need to join your posts table with itself to grab only the newest post for each content_id (which I believe is the author).
$query2 = "SELECT posts.item_id, posts.item_title, posts.item_date from posts
join (select max(item_id) max_id, content_id from posts group by content_id) maxid
on maxid.content_id=posts.content_id and maxid.max_id=posts.item_id
WHERE content_id='$content_id' ";
This opens the door for further optimization. You could grab the authors and their last post in one run.
SELECT content_detail.content_id,
content_detail.title,
content_detail.source_image,
content_detail.url ,
posts.item_id,
posts.item_title,
posts.item_date
FROM content_detail
join posts on content_detail.content_id=posts.content_id
join (select max(item_id) max_id, content_id from posts group by content_id) maxid
on maxid.content_id=posts.content_id and maxid.max_id=posts.item_id
where content_detail.approved='y'
But this could be an overstatement. You should of course try it yourself :)

Related

ORDER before SELECT statement?

I have this query which works great
$sub_query = "SELECT * FROM posts WHERE post_status = 'published' AND
post_user = '{$out}' ORDER BY post_id DESC ";
The query brings back all of a specific users posts ordered by descending post id. The problem is it loops through every post user and orders them accordingly but I want the newest post overall not just the newest post per user.
Here is an image of the results to hopefully help explain better
You can see the query runs for a specific user and then moves on to the next user where I am trying to get the newest post id first
I have tried to follow this similar question but it brought back the same results.
$sub_query = "SELECT * FROM (SELECT * FROM posts ORDER BY post_id DESC)
T WHERE post_status = 'published' AND post_user = '{$out}' ";
Would I be able to order all of the selected posts first? Then use my where statement?
If you want the newest post per user, then remove the where and add a limit:
SELECT p.*
FROM posts p
WHERE p.post_status = 'published'
ORDER BY post_id DESC
LIMIT 1;
I did not understand if what you are looking for is
1) the list of the last post per user
2) the list of all posts sorted by the newest (regardless the user)
In both case you don't need to loop all users, you can extract data ordered just using the query itself (i strongely advise you on this solution).
option 1:
SELECT *
FROM posts
WHERE post_id IN (
SELECT MAX(post_id)
FROM posts
WHERE post_status = 'published'
GROUP BY post_user
)
ORDER BY post_user ASC
option 2:
SELECT *
FROM posts
WHERE post_status = 'published'
post_id DESC

SQL Order By id and Count star not working

I would like to get number of all records and get last record :
$sql_count_sms = "SELECT count(*) as total,content,id FROM android_users_sms WHERE user_id=$id ORDER BY id DESC";
$result_count_sms = mysql_query($sql_count_sms);
$row_num_sms = mysql_fetch_assoc($result_count_sms);
$num_sms = $row_num_sms['total'];
$last_my_sms = $row_num_sms['content'];
I can get number of records but I can't get last content record .
It returns first record !
Where is my wrong ?
Below codes works fine, but I think count(*) is faster than mysql_num_rows .
$sql_count_sms = "SELECT content,id FROM android_users_sms WHERE user_id=$id ORDER BY id DESC";
$result_count_sms = mysql_query($sql_count_sms);
$row_num_sms = mysql_fetch_assoc($result_count_sms);
$num_sms = mysql_num_rows($result_count_sms);
$last_my_sms = $row_num_sms['content'];
Any solution?
The grain of the two results you want is not the same. Without using a sub-query you can't combine an aggregate and a single row into the same result.
Think of the grain as the base unit of the result. The use of GROUP BY and aggregate functions can influence that "grain"... one result row per row on table, or is it grouped by user_id etc... Think of an aggregate function as a form of grouping.
You could break it out into two separate statements:
SELECT count(*) as total FROM android_users_sms WHERE user_id = :id;
SELECT * FROM android_users_sms WHERE user_id = :id ORDER BY id DESC LIMIT 1;
Also, specific to your question, you probably want a LIMIT 1 in combination with the ORDER BY to get just the last row.
Now, counter intuitively perhaps, this should also work:
SELECT count(*), content, id
FROM android_users_sms
WHERE user_id = :id
GROUP BY id, content
ORDER BY id
LIMIT 1;`
This is because we've changed the "grain" with the GROUP BY. This is the real nuance and I feel like this could probably be explained better than I am doing now.
You could also do this with a sub query like so:
SELECT aus.*,
(SELECT count(*) as total FROM android_users_sms WHERE user_id = :id) AS s1
FROM android_users_sms AS aus
WHERE user_id = :id ORDER BY id DESC LIMIT 1;

Select by latest date

I need to select statements where is fixed post id, group by user id and with latest date. Here is what i have:
$bids = "SELECT uid, Max(date_made), bid FROM ".$wpdb->prefix."auction_bids WHERE pid=$pid GROUP BY uid";
In this query is problem only with date, it returns first results, but i need last.
Here is the screen of my database:
You need to obtain the groupwise maximum:
SELECT uid, date_made, bid
FROM ${wpdb->prefix}auction_bids NATURAL JOIN (
SELECT uid, MAX(date_made) AS date_made
FROM ${wpdb->prefix}auction_bids
WHERE pid = $pid
GROUP BY uid
) AS t
WHERE pid = $pid
See it on sqlfiddle.
use min instead of max and grab the id, then join:
$bids = "SELECT ss.uid, ss.min, b.bid FROM ".$wpdb->prefix."auction_bids bid INNER JOIN (SELECT uid, MIN(date_made) as min FROM ".$wpdb->prefix."auction_bids WHERE pid=$pid GROUP BY uid) ss ON ss.uid = bid.uid";
It's not clear what you want from your English. Sorry.
Try this
"SELECT pre.uid, pre.date_made, pre.bid
FROM ".$wpdb->prefix." AS pre
WHERE pre.pid = $pid AND date_made =
(SELECT MAX(pre2.date_made) FROM ".$wpdb->prefix." AS pre2
WHERE pre2.uid = pre.uid)
GROUP BY pre.uid";
A bit complicated but efficient. Similar to eggyal's answer but I'm using theta style coding and hence easy to understand.

SQL: Forum Order by behaviour (in Codeigniter)

Here's the situation:
In my database i have a table with threads, and a table with replies. Both have a Timestamp field.
Now i am developing a forum and wish to order threads in the following manner:
If the thread has replies, then: ORDER BY tblReply.Timestamp DESC
Else, the thread has no replies: ORDER BY tblThread.Timestamp DESC
I do not know how to combine these 2 in one statement.
My query as it is now:
SELECT `PK_ThreadID`, `Title`, `tblUsers`.`Username`, `tblThread`.`Date`, count(tblReply.FK_ThreadID) AS number_replies FROM (`tblThread`)
JOIN `tblUsers` ON `tblUsers`.`PK_UserID` = `tblThread`.`FK_UserID`
LEFT JOIN `tblReply` ON `tblReply`.`FK_ThreadID` = `tblThread`.`PK_ThreadID`
WHERE `isExpertQuestion` = 0 AND `isPublic` = 1
GROUP BY `PK_ThreadID`
ORDER BY max(tblReply.Date)` desc
//Here it only orders by reply date, so threads with no replies appear at the bottom
How do i achieve the ordering i want in this query?
Like this probably:
SELECT `PK_ThreadID`, `Title`,
`tblUsers`.`Username`,
`tblThread`.`Date`,
count(tblReply.FK_ThreadID) AS number_replies
FROM (`tblThread`)
JOIN `tblUsers` ON `tblUsers`.`PK_UserID` = `tblThread`.`FK_UserID`
LEFT JOIN `tblReply` ON `tblReply`.`FK_ThreadID` = `tblThread`.`PK_ThreadID`
WHERE `isExpertQuestion` = 0 AND `isPublic` = 1
GROUP BY `PK_ThreadID`
ORDER BY
CASE WHEN COUNT(tblReply.FK_ThreadID) > 0 THEN tblReply.Timestamp
WHEN COUNT(tblReply.FK_ThreadID) = 0 OR tblReply.FK_ThreadID IS NULL
THEN tblThread.Timestamp
END DESC

mysql select statement and limiting the number of records

I am coding a blog post kind of thing, where the author will post the article and it will be displayed in the front end, my problem starts for selecting the posts as i have to meet certain conditions for posting the news in the front end,
I have 4 fields in the database namely
title
pic_title
pic_brief
pic_detail
you guessed it right apart from the title table the rest of three will hold the path to the images in varchar datatype, which will be used to display as the post, the format of the front end is such that
a) there will be total of eight post
displaying in the front end (eight
entries from the database)
b) there will be three post on the top which will include the value from
the table title, pic_title and
pic_brief (total of 3 values)
c) and the rest five will contain just the title and pic_title
(excluding the three entries of top)
Please NOTE: i want the second query to exclude the top 3 record
which already exist in the top i.e
(first query = 3 post in descending
order, second query = 8 - first 3 = 5
post)
The Order of the Post i want is by id DESC
EDIT: I took the first query as
SELECT * FROM news ORDER BY id DESC LIMIT 3
Now if i take the same second query and try populating the values by desc order again the same records will be accessed
In simple words i want a query that will skip the last three records order by id DESC
How do i achieve this feat in PHP?
If you just want the SQL, here it is:
First query
SELECT * FROM `table` LIMIT 3
Second query
SELECT * FROM `table` LIMIT 3,5
(where table is the name of your table of course. Of course you may want to add some ORDER BY clause. To execute these queries in PHP, I suggest reading the manual. If you have any specific problems after doing so, then you can post a new question.
This is a situation where I'd likely opt to select all eight records at once - the less trips to the database, the better.
SELECT t.title,
t.pic_title,
t.pic_brief
FROM TABLE t
ORDER BY t.id DESC
LIMIT 8
...because the rest is just presentation:
$query = sprintf("SELECT t.title,
t.pic_title,
t.pic_brief
FROM TABLE t
ORDER BY t.id DESC
LIMIT 8");
// Perform Query
$result = mysql_query($query) or die( mysql_error() );
$rowcount = 1;
// Use result
while ($row = mysql_fetch_assoc($result)) {
if(rowcount <= 3) {
echo $row['title']
echo $row['pic_title']
echo $row['pic_brief']
} else {
echo $row['title']
echo $row['pic_title']
}
++$rowcount;
}
first query will be like this
"select title, pic_title , pic_brief from table_name order by post_id desc limit 0 , 3"
and rest of five will be
"select title, pic_title from table_name order by post_id desc limit 3 , 5"
second query will exclude the three results returned by first query...
If you want more perfection you can collect all three Ids returned by first query and can add NOT IN in second query.
"select title, pic_title from table_name where post_id not in (1,2,3) order by post_id desc limit 0 , 5";

Categories