MySQL - Skip Duplicate WordPress Entries - php

I'm writing a script to display the 10 most recently "active" WordPress blog posts (i.e. those with the most recent comments). Problem is, the list has a lot of duplicates. I'd like to weed out the duplicates. Is there an easy way to do this by changing the MySQL query (like IGNORE, WHERE) or some other means? Here's what I have so far:
<?php
function cd_recently_active() {
global $wpdb, $comments, $comment;
$number = 10; //how many recently active posts to display? enter here
if ( !$comments = wp_cache_get( 'recent_comments', 'widget' ) ) {
$comments = $wpdb->get_results("SELECT comment_date, comment_author, comment_author_url, comment_ID, comment_post_ID, comment_content FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT $number");
wp_cache_add( 'recent_comments', $comments, 'widget' );
}
?>

Look at the DISTINCT option for the SELECT statement. Or alternatively the GROUP BY syntax (look at the same link). Though they work in different ways, these would be the two methods most likely to help you get exactly what you want.

I thought I had figured it out using GROUP BY, but now I'm not so sure. Here is the code:
if ( !$comments = wp_cache_get( 'recent_comments', 'widget' ) ) {
$comments = $wpdb->get_results("SELECT comment_post_ID, comment_author, comment_date FROM $wpdb->comments WHERE comment_approved = '1' GROUP BY comment_post_ID ORDER BY comment_date_gmt DESC LIMIT $number");
wp_cache_add( 'recent_comments', $comments, 'widget' );
}
The single change is to add GROUP BY comment_post_ID (the field I wanted to be unique). Unfortunately, this "breaks" the function; it's frozen and does not update.
I also could not get DISTINCT to work. One comment I'm following up on to figure this out came from http://www.webmasterworld.com/forum88/9204.htm
In particular, comment #:1259236 by ergophobe says, "You left out the GROUP BY. Without that, you will get multiple results for a given topic_id b/c the row will not be distinct. In fact, the distinct is not necessary, just the GROUP BY."
Still looking....

Related

How can I order the results of an SQL query by the count of another table based on a shard ID?

I have an SQL query that fetches posts from a database. Everything works fine, but now I need to order the results by the number of comments each post has. The comments are on a separate table and they have a post_id column that links it to the post. I need to order the posts by the count of the comments table based on a shard ID? I have tried everything but every time I try to add something to my query it stops running completely and leaves my page blank. I need help to know where to put the other JOIN statement. This is my query:
$union = "UNION ALL
(
SELECT DISTINCT wallposts.p_id,wallposts.is_profile_notes,wallposts.times_viewed,wallposts.columnTimesShared,
wallposts.marked,wallposts.secure_id,wallposts.reshared,wallposts.group_id,
wallposts.totaluploads,wallposts.WallUploadID,wallposts.type,
wallposts.value,wallposts.media,wallposts.youtube,wallposts.post_type,
wallposts.privacy,wallposts.tagedpersons,wallposts.with_friends_tagged,wallposts.emotion_head,wallposts.selected_emotion,wallposts.title,
wallposts.url,wallposts.description,wallposts.cur_image,
wallposts.uip,wallposts.likes,wallposts.userid,
wallposts.posted_by,wallposts.post as postdata,wallusers.*,
UNIX_TIMESTAMP() - wallposts.date_created AS TimeSpent,
PosterTable.mem_pic as posterPic, PosterTable.gender as posterGender,PosterTable.oauth_uid as poster_oauth_uid, PosterTable.username as posterUsername,
PosterTable.mem_fname as posterFname,PosterTable.work as posterWork,
PosterTable.mem_lname as posterLname,walllikes_track.id as PostLikeFound,wallposts.date_created
FROM
wallusers,wallusers as PosterTable, wallposts
LEFT JOIN walllikes_track
ON wallposts.p_id = walllikes_track.post_id AND walllikes_track.member_id = ".$user_id."
WHERE
wallusers.active = 1
AND
PosterTable.active = 1
AND
wallposts.group_id IN (".$groups.")
AND
wallposts.group_id != 0
AND
PosterTable.mem_id = wallposts.posted_by
AND
wallposts.marked < ".$this->flagNumber."
AND
wallusers.mem_id = wallposts.posted_by ) ";
The comments table is called wallcomments and it has a column called post_id. I know I need to use JOIN and COUNT but I don't know where to put it within my current code.
Try this query, I didn't run but i updated it.
SELECT wallposts.p_id,wallposts.is_profile_notes,wallposts.times_viewed,wallposts.columnTimesShared,
wallposts.marked,wallposts.secure_id,wallposts.reshared,wallposts.group_id,
wallposts.totaluploads,wallposts.WallUploadID,wallposts.type,
wallposts.value,wallposts.media,wallposts.youtube,wallposts.post_type,
wallposts.privacy,wallposts.tagedpersons,wallposts.with_friends_tagged,wallposts.emotion_head,wallposts.selected_emotion,wallposts.title,
wallposts.url,wallposts.description,wallposts.cur_image,
wallposts.uip,wallposts.likes,wallposts.userid,
wallposts.posted_by,wallposts.post as postdata,wallusers.*,
UNIX_TIMESTAMP() - wallposts.date_created AS TimeSpent,
PosterTable.mem_pic as posterPic, PosterTable.gender as posterGender,PosterTable.oauth_uid as poster_oauth_uid, PosterTable.username as posterUsername,
PosterTable.mem_fname as posterFname,PosterTable.work as posterWork,
PosterTable.mem_lname as posterLname,walllikes_track.id as PostLikeFound,wallposts.date_created
FROM
wallusers,wallusers as PosterTable, wallposts
WHERE
wallusers.active = 1
AND
PosterTable.active = 1
AND
wallposts.group_id IN (".$groups.")
AND
wallposts.group_id != 0
AND
PosterTable.mem_id = wallposts.posted_by
AND
wallposts.marked < ".$this->flagNumber."
AND
wallusers.mem_id = wallposts.posted_by ) " AND wallposts.p_id = walllikes_track.post_id AND walllikes_track.member_id = ".$user_id.";
A more readable query might look like this...
At least then we'd have a chance.
SELECT DISTINCT p.p_id
, p.is_profile_notes
, p.times_viewed
, p.columnTimesShared
, p.marked
, p.secure_id
, p.media...
FROM wallposts p...

How to make two $db->query from the same table with two different ORDER by column that each other stand independenty in one php page?

I want to make two blocktables in one page from the same DB table. The first blocktable I want to ORDER it by "posted_date" column, and the second I want to ORDER it by "numviews" column. I want the both blocktables not influence each other, altough they're on the same page. Is it possible?
I have made like this,
first block
$popresult = $db->query('
SELECT
t.id,
t.poster, f.id AS forum_id,
f.forum_name,
t.subject,
t.mainimg,
posted_date,
t.num_views
FROM '.$db->prefix.'forums
ORDER BY 'posted_date' DESC
LIMIT '.$numtopik.'', true)
or error('Tidak dapat mengambil topik populer', __FILE__, __LINE__, $db->error());
second block
$popresult = $db->query('
SELECT
t.id,
t.poster,
f.id AS forum_id,
f.forum_name,
t.subject,
t.mainimg,
posted_date,
t.num_views
FROM '.$db->prefix.'forums
ORDER BY t.num_views DESC
LIMIT '.$numtopik.'', true)
or error('Tidak dapat mengambil topik populer', __FILE__, __LINE__, $db->error());
but it still got error to fetch.
Can anybody help me please?
In your first query you don‘t order by the date, but use the value of $date in the LIMIT part of your query.
So your last part in your first query, should be more like:
[...] ORDER BY t.`yourDateColumnHere` DESC LIMIT '.$yourLimitVariableHere [...]
Hope that helps! If not, feel free to add a comment!

Can't retrieve zero values when using COUNT and GROUP together

I'm struggling with a MYSQL query, when using COUNT and GROUP together it's excluding any rows that have a count of 0. I understand why this is happening but can't work out how to get around it. I've read up on potential solutions presented to those with a similar problem but I cannot see the link between the two that would allow me to solve it.
Can anybody help?
$query = "SELECT id, class_date, class_id, COUNT(*) AS reserve_count
FROM bookings
WHERE booking_status='#RESERVE#'
GROUP BY class_date, class_id
ORDER BY class_date ASC, class_id ASC" ;
$result = mysqli_query($sql,$query);
while($row = mysqli_fetch_assoc($result)) {
$bookings[$row['id']] = array('class_date' => $row['class_date'], 'class_id' => $row['class_id'], 'reserve_count' => $row['reserve_count']);
}
Logically, there shouldn't be any row with zero count because booking table should only have classes that are booked.

How to retrieve all posts with all comments using 2 SQL queries

I am trying to make a page with a list of posts, and underneath each post all the comments belonging to that post. Initially I wanted to use just one query to retrieve all the posts + comments using the SQL's JOIN, but I find it impossible to for example retrieve a post with multiple comments. It only displays the posts with a maximum of 1 comment per post, or it just show a post multiple times depending on the amount of comments.
In this related question, somebody talked about using 2 queries:
How to print posts and comments with only one sql query
But how do I do this?
I've got the query and a while loop for posts, but I obviously don't want to run a query for comments for each post inside that loop.
$getPost = mysql_query('SELECT p.post_id,
p.user_id,
p.username,
p.content
FROM post p
ORDER BY p.post_id DESC');
while($row = mysql_fetch_array($getPost))
{
...
}
Table structure (reply is the table for storing comments):
POST (post_id (primary key), user_id, username, content, timestamp)
REPLY (reply_id (primary key), post_id, username, reply_content, timestamp)
You can do it in a single query, which is OK if the amount of data in your original posts is small:
$getPost = mysql_query('SELECT
p.*,
r.reply_id, r.username r_username, r.reply_content, r.timestamp r_timestamp
FROM post p
left join reply r
ORDER BY p.post_id DESC'
);
$posts = array();
$last_id = 0;
while($row = mysql_fetch_array($getPost))
{
if ($last_id != $row['post_id']) {
$posts[] = array(
'post_id' => $row['post_id'],
'user_id' => $row['user_id'],
'username' => $row['username'],
'content' => $row['content'],
'timestamp' => $row['timestamp'],
'comments' => array()
);
}
$posts[sizeof($posts) - 1]['comments'][] = array(
'reply_id' => $row['reply_id'],
'username' => $row['r_username'],
'reply_content' => $row['reply_content'],
'timestamp' = $row['r_timestamp']
);
}
Otherwise, break it into two queries like so:
$getPost = mysql_query('SELECT
p.*,
FROM post p
ORDER BY p.post_id DESC'
);
$rows = array();
$ids = array();
$index = array();
while($row = mysql_fetch_assoc($getPost)) {
$row['comments'] = array();
$rows[] = $row;
$ids[] = $row['post_id'];
$index[$row['post_id']] = sizeof($rows) - 1;
}
$getComments = mysql_query('select r.* from replies r where r.post_id in ("'
. join('","', $ids)
. '")');
while ($row = mysq_fetch_assoc($getComments)) {
$rows[$index[$row['post_id']]]['comments'][] = $row;
}
... Or something like that. Either option allows you to litter your first query with WHERE clauses and so forth to your heart's content. The advantage of the 2nd approach is that you don't re-transmit your original post data for each comment!
In order to also get those posts without comments, you need to use a LEFT OUTER JOIN. In that case, any row in the first table without any corresponding rows in the second table will be paired with a row consisting of null values.
SELECT * FROM posts
LEFT OUTER JOIN comments ON posts~post_id = comments~post_id;
By the way: there is also a RIGHT OUTER JOIN. When you would use that, you would get all comments, including those where the parent post got lost somehow, but no posts without comments.

Why won't ORDER BY work?

I didn't write this code, it's from the Racetracker (http://sourceforge.net/projects/racetracker/), but I've been trying to make a couple modifications.
I'm trying to make a brief teams standings list, and thus limit it to 5 teams. The teams standings page has "ORDER BY SUM(driverpoints)" in it, but it doesn't do anything (the page uses Javascript to manually sort the HTML table). Furthermore, when I try to add a LIMIT 5, it similarly does nothing, it simply prints all the different teams. Here's the relevant code (I removed a lot of repetitive ORs here, as there were 43 of the OR drivername = '$thenames[1]' qualifiers, they don't affect whether or not the ORDER BY and LIMIT parts work):
$total= mysql_query("SELECT SUM(driverpoints), SUM(events), SUM(firstplace),
SUM(qual1stplace), SUM(lapsseason), SUM(lapsledseason), SUM(top5season),
SUM(top10season), SUM(provisionals)
FROM `$whatseriestable`
WHERE `year` = $siteyear AND `drivername` = '$thenames[0]'
OR `drivername` = '$thenames[1]'
ORDER BY `SUM(driverpoints)` DESC LIMIT 5");
What is also puzzling is that ORDER BY and LIMIT work fine in the drivers standings summary:
$stn= mysql_query("SELECT * FROM `$whatseriestable`
WHERE `year` = $siteyear
ORDER BY `driverpoints` DESC LIMIT 10");
Why doesn't this work with the teams standings?
Its probably all just your WHERE clause... AND's take a precidence over the or so
WHERE
`year` = $siteyear
AND `drivername` = '$thenames[0]'
OR `drivername` = '$thenames[1]'
Is being interpreted as
WHERE
( year condition and first driver condition )
OR ( second driver )
I think what you mean is
WHERE
( year condition )
and ( first driver condition OR second driver )
Wrap your driver conditions in ( ) parens.

Categories