SQL joining wordpress tables - mysql

I am struggling with an SQL query to join 3 tables to return specific results.
Anyone familiar with wordpress may be able to assist as I am using word press to power post interactions with the db behind the scenes but am building a custom UI. The three tables are: -
posts (**ID**, post_title, post_content, post_modified_gmt)
term_relationships (**object_id**, term_taxonomy)
terms (**term_id**, name, slug)
I have got as far as..
SELECT posts.post_title FROM posts
INNER JOIN term_relationships
ON posts.ID = term_relationships.object_id
Which returns a list of all the post titles that have a matching ID number in term_relationships. However term names are in the table 'terms' and the ID's don't match the other two tables. In the terms table the term_id refers to the name of the term, e.g
term_id = 2, name = blog
Basically I am trying to achieve a query whereby if I set the term_id = 2 it returns all the rows from the table posts that have the term relationship to blog, meaning the query returns all blog posts and I am completely lost!
Can anyone give me a few pointers? my mind is boggled.

I managed to achieve the result I was looking for with the following query, but would still appreciate some pointers should anyone stumble upon this and have the inclination :)
SELECT * FROM posts
INNER JOIN term_relationships
ON posts.ID = term_relationships.object_id
WHERE term_relationships.term_taxonomy_id = 2
AND posts.post_type = 'post'
AND posts.post_status = 'publish'
ORDER BY posts.post_modified_gmt ASC
LIMIT 0,5

Related

How can I efficiently query 'Like' data from MySQL?

I am developing a social network iOS app using a PHP backend with a MySQL database. I have 3 tables in my database to store Posts, Comments and Likes.
Currently, the app requests up to 50 posts at a time which includes various specific data. I do this using a SELECT query from MySQL. My 'Likes' are stored in the 'Likes table' as 1 Like per row. This includes their username and which post they 'liked'.
When the app is refreshed, I need to gather the 'Likes' data on the posts that have just been loaded. My problem is that I do not know the best way to query MySQL to return all associated likes with that user. This means that when I load some posts, I want the user to see which posts they have already liked.
Here is a visual description of my problem:
Please understand that up to 50 of these posts will be shown at one time.
There is several way to do this and depending on your project you might want to optimise my answer.
I assume your Likes table has a structure of (int) id, (int) user_id, (int) post_id.
To answer directly to your question (about doing a query only for the refresh), the next MySQL query will give you the list of post_id liked by the user. You need to replace %user_id% by the id of the user and %post_ids% by the list of the 50 posts ids, separated by a comma:
SELECT post_id
FROM Likes
WHERE user_id = %user_id% AND
post_id IN (%post_ids%)
However, if the refresh implies the whole page (and not only an AJAX request or so on) I would consider implementing this directly in the query getting the posts. For example :
SELECT p.id, p.content, p...., l.id AS `Liked`
FROM Posts AS p
LEFT JOIN Likes AS l
ON p.id = l.post_id AND
l.user_id = %user_id%
WHERE ...
Please also consider adding indexes on the right columns.
As promised, my solution is here:
SELECT `posts`.`postnumber`, `posts`.`message`, `likes`.`didLike`
FROM `posts`
LEFT JOIN `likes`
ON `posts`.`postnumber`=`likes`.`post_id`
AND `likes`.`user_id`='USERNAME';

Filter out records with at least one association that doesn't meet given conditions

Let's say I have posts and categorizations.
Post(id)
Categorization(post_id, topic_id)
I'd like to fetch posts that don't belong to a specific topic id.
In my case I have to use an inner join when joining Post to Categorizations as i have other filters to execute.
How do I go about this?
I have tried the following:
Post.joins(:categorizations).where("categorizations.topic_id != ?", doomed_topic_id)
But this returns posts that still have OTHER topics. it only works with posts with just one single topic that happens to be the unwanted one.
For instance, if I have a post with 2 categories (the doomed topic_id AND another topic) this query fails and actually fetches it, instead of filtering it out.
Try:
Posts.where('not exists
(select * from categorizations
where post_id = posts.id and
topic_id = ?)', doomed_id)

making a query from several categories

I have a blog, and I want to make a sql query, to provide all the blogs that belong to several arbitrary categories.
I thought I could do it with
SELECT * FROM `blog` WHERE `blog_category_id` IN($categories) ORDER BY RAND() LIMIT 10
But then I forgot that the categories come from another table, and now I am really struggling to work this out.
So I am trying to return all the info from the rows in the blog table, and find the blogs from the blogs_to_cats table
blogs_to_cats table contains blog_id and blog_category_id.
So what I have is an array of blog_category_id's, from here I want to generate the query.
What is the correct sql query to accomplish something like this, some sort of array table join?
SELECT blog.*
FROM blog b
INNER JOIN blog_to_cat bc ON b.id = bc.blog_id
WHERE bc.blog_category_id IN $categories

Retrieve first few comments on a post from MySQL table

You know how the Facebook home feed lists all the recent posts? It shows the user that posted, their actual post and then the first few comments attached to that post. That's what I'm trying to achieve, but I'm having a hard time building a single query that can gather all that data.
I have 3 tables: Uses, Posts and Comments. Each has a unique ID, but they reference each other's IDs. i.e, the Comments table has columns for the user_id of the user who posted and the post_id of the post it is attached to.
At the minute I'm querying SQL to gather all the posts. I join my Users and Comments tables to learn the Username of the poster and a total of how many comments the post has, like so:
$query = "
SELECT `posts`.`id`,`posts`.`message`,`posts`.`link`,
`posts`.`posted`,`posts`.`category`,`posts`.`user_id`,
`users`.`username`,
count(`comments`.`id`)
FROM `posts`
INNER JOIN `users`
ON `posts`.`user_id`=`users`.`id`
JOIN `comments`
ON `comments`.`post_id`=`posts`.`id`
WHERE `posts`.`group_id` = '$id'
AND `posts`.`category`='$filter'
GROUP BY `posts`.`id`
ORDER BY `posts`.`posted`
DESC
";
But instead of finding how many comments a post has, I would instead like to read the first few posts. Can anyone think of a way to achieve this with just the one query?
You can use the LIMIT clause to the the "first" posts. By making the "first posts" a subquery and then joining in the comments you can get everything in a single query. The comments should be left-joined in case of posts with no comments.
Notes:
This query is untested, but it should be close.
This will get all comments for the first few posts, so you'll need to limit the display of "max 3 comments per post" using the front-end display code.
It may be possible to limit comments to 3 per post within this query using variables, but that's not something I know how to do.
Here's the query:
SELECT
FirstPosts.id,
FirstPosts.message,
FirstPosts.link,
FirstPosts.posted,
FirstPosts.posts,
FirstPosts.user_id,
FirstPosts.username,
comments.<< your comment column >>
FROM (
SELECT `posts`.`id`,`posts`.`message`,`posts`.`link`,
`posts`.`posted`,`posts`.`category`,`posts`.`user_id`,
`users`.`username`
FROM `posts`
INNER JOIN `users`
ON `posts`.`user_id`=`users`.`id`
WHERE `posts`.`group_id` = '$id'
AND `posts`.`category`='$filter'
ORDER BY `posts`.`posted` DESC
LIMIT 20) FirstPosts
LEFT JOIN comments ON FirstPosts.id = comments.post_id
ORDER BY FirstPosts.Posted, comments.<< column you use to determing comment order >>
If you determine comment order by a date or sequence, you'll have to ORDER BY FirstPosts.Posted, comments.whatever DESC.
Hope this helps!

Help building a sql query that uses inner join

I am trying to build a sql query that I think it involves inner joins, but I can't figure it out. Here's the model:
There's two tables: comments, posts
Among many columns, there's the following important ones: comments.id, comments.user_id (owner), comments.post_id (reference to posts table), posts.id, posts.editor_id (which is the person, ie, owner of post).
I want to get the comments that either
1) current user has written, so something like:
select * from comments where user_id = <<current_user_id>>
2) (Assume current_user is editor). Get all comments that belong to a post that you have created.
This is what I have, but I get multiple lines....what am I missing?
select * FROM comments INNER JOIN posts ON comments.post_id = <<test_id>>
WHERE posts.editor_id = <<current_user.editor_id>>;
If you could give me a sql query that includes both of these things, that would be amazing.
Thanks!
Im not sure what you mean by "multiple lines" as you would return a row for each comment.
This should do it.
SELECT comments.*
FROM comments
INNER JOIN posts
ON comments.post_id = posts.id
WHERE posts.editor_id = #editorID;
I want to get the comments that either 1) current user has written, so something like: select * from comments where user_id = <>
That's correct. What's wrong with that?
Get all comments that belong to a post that you have created. This is what I have, but I get multiple lines
Well... you're supposed to. Looking at the schema it's indeed a post could contain many comments. The query given by tyrongower should do what you want.
Going with your requirements, this should work for you:
SELECT * FROM comments
WHERE (user_id = 1)
OR (post_id IN (SELECT id FROM post WHERE editor_id = 1))
In the above query "1" is used as a sample and should be replace with the id of current user.