Select data from two tables with speed - php

I have two tables that I want to select from. I have a table called articles which stores various articles for my content management system and I have another called articles_meta_data that stores meta data for the articles table. In order to get an article's meta data, you select from articles_meta_data using the article Id. My code is here and works perfectly. Is there a way I can optimize the code and make it faster?
$result = mysql_query("SELECT * FROM articles");
while ($row = mysql_fetch_object($result)) {
$result2 = mysql_query("SELECT * FROM articles_meta_data WHERE article_ID=" . $row->ID);
while ($row2 = mysql_fetch_object($result2)) {
var_dump($row2);
}
}

join the tables so you will only query the database once, eg
SELECT b.*
FROM articles a
INNER JOIN articles_meta_data b
ON a.ID = b.article_ID
To further lean more about join, please see the link below
Visual Representation of SQL Joins

you should use join query so that you dont need to fire two queries, but first you have to decide which join to use for this check this link http://www.firebirdfaq.org/faq93/
here we will use JOIN so that records with same value for columns articles.ID and articles_meta_data.article_ID will be selected
SELECT *,articles_meta_data.field1,articles_meta_data.field2 from articles JOIN articles_meta_data ON articles.ID = articles_meta_data.article_ID

You can also do something like this..
Select * from articles JOIN articles_meta_data ON ID = article_ID
Hope this may also help you in some other way.

Related

Retrieving data from multiple tables mysql php

I have 2 tables MOVIES and SHOWS.
MOVIES tables contains:
id, name, image, description.
SHOWS table contains:
id, movieid, description.
I'm executing mysql statement to retrieve records from SHOWS table, i'm getting all the records normally. Again I'm executing another mysql statement to get image from MOVIES table based on movies table id which i'm getting from first query.
Is there any simple way to retrieve all the records from SHOWS table along with movie image?
These are my queries:
$qry1 = mysql_query("SELECT * FROM shows WHERE id='1'");
$res = mysql_fetch_array($qry1);
$movieid = $res['movieid'];
$qry2 = mysql_query("SELECT image FROM movies WHERE id='$movieid'");
SELECT t1.id, t1.movieid, t1.description, t2.image FROM SHOWS as t1
INNER JOIN
MOVIES as t2 ON t1.id = t2.id
Some sql join docs
or you can try this, i was not sure witch id is from where:
SELECT id, movieid, description, image FROM SHOWS
INNER JOIN MOVIES
ON id = movieid
Some foreign key docs
Here I am writing with out join you can all so use nested select queries
select movies.image from movies where movies.id in(Select shows.movieid form shows where shows.id= 1);
You can retrieve data from multiple tables from one server at the same time. There is a lot of ways to achieve this operation which is called join. One of the possibility would be the LEFT JOIN like this:
SELECT t1.field1, t1.field2,..., t2.field1, t2.field2, ..., t2.fieldn
FROM table1 AS t2
LEFT JOIN talble2 AS t2 ON t2.some_field = t1.anothed_filed
WHERE some_condition
In you case:
SELECT s.*, m.image
FROM SHOWS AS s
LEFT JOIN movies AS m ON s.movieid = m.id
WHERE some_condition
for more info see the documentation on https://dev.mysql.com/doc/refman/5.7/en/join.html

MYSQL and PHP loop and grab just one item from a joint table?

I am currently building a custom CMS to help me learn PHP and MYSQL. I have two database tables 'users' and 'articles'. When the user submits an article, the field 'author_id' in the 'articles' table places to the users 'users_id' from the 'users' table. This way i can join the tables and get all the articles from that user. Now i am trying to make a feature section on the home page. I want to loop through all authors/users and get one article from that user. Here is a sample of my code...
$author= db::getInstance()->query("SELECT * FROM users, articles WHERE user_id = author_id");
foreach($author->results() as $author) {
echo $author->profile_img;
echo $author->user_name
echo $author->article_title;
}
This works fine if the user has only posted one article but if there are more than 1 then it will loop through all the posts of that user. I just want to echo 1 article from each user but not sure how i can achieve this. Can anyone point me in the right direction?
Many Thanks,
Louis Lombardi
If you want one arbitrary article for each user, you can use a MySQL (mis)feature that allows you to do "partial" aggregations:
SELECT u.*, a.*
FROM users u JOIN
articles a
ON u.user_id = a.author_id
GROUP BY u.user_id;
My preferred method for a random article would be more like this:
select u.*, a.*
from (select u.*,
(select a.article_id
from articles a
where a.author_id = u.user_id
order by rand()
limit 1
) as article_id
from users u
) u join
articles a
on u.article_id = a.article_id;
Finally, my preferred method for getting the first/last would look something like this:
SELECT u.*, a.*
FROM users u JOIN
articles a
ON u.user_id = a.author_id
WHERE a.article_id = (SELECT MAX(a2.article_id)
FROM articles a2
WHERE a2.author_id = u.author_id
);
You can use MySql limit:
SELECT * FROM users, articles WHERE user_id = '$author_id' limit 0,1
Complete documentation: https://dev.mysql.com/doc/refman/5.5/en/limit-optimization.html

Using SQL JOIN function but choosing which columns are selected

Previously, I asked the following question: How do I combine tables with SQL?
I wanted to grab data from my movies db but order the information by my history db.
This is how I'm using the data:
$movie = $db2->query("SELECT * FROM movies m INNER JOIN history h ON h.movie_id = m.id WHERE h.user_id = $id3 ORDER BY h.id LIMIT $start, $per_page");
Please don't worry about $db2, $id3, $start or $per_page. All of these variables are working properly...
I then use $movie with $movie3:
while($movie3 = mysqli_fetch_array($movie)) {
echo $real_id = $movie3["id"];
}
To be clear, everything is working properly with the data and ordering. However, $real_id is equal to the id from the history db, not the movies db. Can I have the best of both worlds? Keep what I have but change the content of $real_id?
UPDATE: How do I now select the proper id?
This is my new query thanks to #Jay Blanchard
$movie = $db2->query("SELECT m.*,h.* FROM movies m INNER JOIN history h ON h.movie_id = m.id WHERE h.user_id = $id3 ORDER BY h.id LIMIT $start, $per_page");
When I do this:
while($movie3 = mysqli_fetch_array($movie)) {
echo $movie3["id"];
}
The id is still being retrieved by my history db. How do I now select the proper id?
My guess would be something like this:
echo m.$movie3["id"];
Any feedback or ideas would greatly be appreciated!
You have to tell the select the data to get -
SELECT m.id AS mid, h.id AS hid FROM movies m INNER JOIN history h...
Without specificity you will encounter column ambiguity which leads to heartache and depression. A comment in your other question pointed this out, but it bears repeating: select specific columns and do not use * ever.
EDIT: (above query snippet modified)
Now that the query is asking for specific columns and I have used good aliases for each column I can echo the columns easily:
echo $row['mid'];

Show all posts for people you follow

I have got 2 tables, t_feed and t_follow.
t_feed has -
feedID
userID
posts
t_follow has -
followID
userID
following
How would I display all the posts for all the users that someone follows?
Use a JOIN:
SELECT t_feed.posts FROM t_feed JOIN t_follow ON t_feed.userID = t_follow.following;
$query="select* from t_follow INNER JOIN t_feed on t_follow.userid=t_feed.userid where userid=".$userid;
here $userid is userid of current user. Pass this query to recieve output.
If you're using a MySQL database for this, you could check out Tizag's tutorial on MySQL Joins: http://www.tizag.com/mysqlTutorial/mysqljoins.php:
$query = "select feedID, posts from t_follow INNER JOIN t_feed on t_follow.userid = t_feed.userid where userid=".$userid;

get count of posts based on count(*)

i am trying to get number of posts that i have
Here is my query
$Query="
SELECT t.*,u.*,c.*
FROM posts as t
LEFT JOIN relations as r on r.post_id = t.post_id
LEFT JOIN users as u on t.auther_id = u.auther_id
LEFT JOIN categories as c on c.cate_id = r.cate_id
GROUP BY t.post_id
";
$Query=mysql_query($Query);
$numberOfPosts=mysql_num_rows($Query);
This query is works very well
but i am trying to convert it, i want make it faster
i want use count(*) instead of t.*
because when i use t.*, it gets the full data of posts and categories
but i want to get count only, So i decided to use count(*) but i don't know how to use it with query like this
Edit
i've replaced SELECT t.*,u.*,c.* with SELECT count(t.*)
But i got mysql Error Warning: mysql_fetch_assoc(): supplied argument
Edit 2:
i am trying SELECT count(t.post_title)
I Got this results
Array ( [count(t.post_id)] => 10 )
But i have only 2 posts!
$Query="
SELECT t.*,u.*,c.*
FROM posts as t
LEFT JOIN relations as r on r.post_id = t.post_id
LEFT JOIN users as u on t.auther_id = u.auther_id
LEFT JOIN categories as c on c.cate_id = r.cate_id
GROUP BY t.post_id
";
$Query=mysql_query($Query);
$numberOfPosts=mysql_num_rows($Query);
Let's take a step back and analyze this query for a moment.
You're selecting everything from three out of four tables used in the query. The joins create some logic to limit what you select to the proper categories, authors, etc. At the end of the day you are getting a lot of data from the database, then in PHP simply asking it how many rows were returned (mysql_num_rows). Instead, what #Dagon is trying to suggest in comments, is that you have MySQL simply count the results, and return that.
Let's refactor your query:
$query = "
SELECT COUNT(t.post_id) AS qty
FROM posts as t
LEFT JOIN relations AS r ON r.post_id = t.post_id
LEFT JOIN users AS u ON t.auther_id = u.auther_id
LEFT JOIN categories AS c ON c.cate_id = r.cate_id
GROUP BY t.post_id
";
$result = mysql_query($query);
$result_row = mysql_fetch_assoc($result);
$numberOfPosts = $result_row['qty'];
(You could also use Barattlo's custom execute_scalar function to make it more readable.)
I would need to see your table structures to be of more help on how to optimize the query and get the desired results.
try doing this:
$Query="
SELECT count(t.*) as count_all
FROM posts as t
LEFT JOIN relations as r on r.post_id = t.post_id
LEFT JOIN users as u on t.auther_id = u.auther_id
LEFT JOIN categories as c on c.cate_id = r.cate_id
GROUP BY t.post_id
";
$Query=mysql_query($Query);
$numberOfPosts=mysql_num_rows($Query);
You want to do
SELECT count(t.id) AS count FROM ....
//do query with PDO or whatever you are using
$rows = mysql_fetch_assoc();
$num_rows = $rows['count'];
You should probably simply use
SELECT count(*) as postingcount FROM posts
Why?
Because you do not have a WHERE clause, so there are no restrictions. Your JOINS do not ADD more rows to the resultset, and in the end your GROUP BY merges every duplicate occurance of a post_id that might have occurred because of joining back into one row. The result should only be counted, so assuming that the real number you want to know is the number of data sets inside the table posts, you do not need any join, and doing count(*) really is a very fast operation on tables in MySQL.
Remember to check if mysql_query returns false, because then you have to check mysql_error() and see why your query has an error.

Categories