Using SQL JOIN function but choosing which columns are selected - php

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'];

Related

Table only shows 2 total results but instead shows 4 results = 2 duplicates?

$get_comment = $dbh->query("SELECT sc.sc_content, sc.sc_sid, sc.sc_date, m.username FROM schedule_comments AS sc LEFT JOIN members AS m ON sc.sc_uid = m.uid WHERE sc.sc_sid = '$view'");
Right there is my query to get a members username so that it can display... BUT INSTEAD.
It duplicates my results, here's a screenshot below.
http://i.gyazo.com/4d0ab0a354bb36294afe17c8c5efd2c3.png
As you can tell, the date these rows were inserted are the exact same. Only 2 rows are different.
I don't think there's anything wrong with this query, I think it's correct. What am I doing wrong here?
Try adding the DISTINCT keyword to your query:
$get_comment = $dbh->query("SELECT DISTINCT sc.sc_content, sc.sc_sid, sc.sc_date, m.username FROM schedule_comments AS sc LEFT JOIN members AS m ON sc.sc_uid = m.uid WHERE sc.sc_sid = '$view'");
It should return only, well, distinct results :-)

Select data from two tables with speed

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.

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.

possible syntax error in mysql query?

im still new to queries that call multiple tables with one call, here is my old query string,
$sql = "SELECT id,category,title,seo_url,product_line,look_for_terms,image,rating FROM sphinx_index WHERE id IN ($entry_ids) ORDER BY rating DESC";
and heres is the new one im trying to get working,
$sql = "SELECT a.id, a.category, a.title, a.seo_url, a.product_line, a.look_for_terms, a.image, a.rating a.status, c.username FROM sphinx_index a, entry b, users c WHERE a.id IN ($entry_ids) AND b.user_id = c.id ORDER BY a.rating DESC";
There's no real question there, but if you wanna see what MySQL thinks about it: execute it and fetch the error.
$result = mysql_query($query);
if($result === false)
{
echo mysql_error();
}
Be more specific next time anyway.
It looks weird in your SQL request that table a is not joined with b or c ;
This kind of join only rarely makes sense.
Maybe you miss for example this additional clause in your WHERE :
AND a.id = c.id
but it is hard to guess what your tables are doing and what is the correct way to join a with the 2 other tables.

PHP / MySQL - Confusing Query

Im trying to construct a query that goes over 3 tables and im COMPLETELY stumped ... my knowledge limit is basic 1 table query and i need some help before i stick my head in a blender.
I have the following query
SELECT * FROM internalrole WHERE introle = $imarole
Im fine with that part .. its the next thats getting me all stressed.
That query returns the following columns ( id, user_id, introle, proven, used )
What i then need to do is take the user_id from the results returned and use it to get the following
SELECT * FROM users WHERE id = user_id(from previous query) AND archive = 0 and status = 8
I need to put that into 1 query, but wait, theres more .... from the results there, i need to check if that user's 'id' is in the availability table, if it is, check the date ( column name is date ) and if it matches todays date, dont return that one user.
I need to put all that in one query :S ... i have NO IDEA how to do it, thinking about it makes my head shake ... If someone could help me out, i would be eternaly grateful.
Cheers,
Use INNER JOIN, which links tables to each other based on a common attribute (typically a primary - foreign key relationship)
say an attribute, 'id', links table1 and table2
SELECT t1.att1, t2.att2
FROM table1 t1
INNER JOIN table2 t2
ON t1.id = t2.id --essentially, this links ids that are equal with each other together to make one large table row
To add more tables, just add more join clauses.
SELECT u.*
FROM internalrole ir
INNER JOIN users u
ON ir.user_id = u.id
AND u.archive = 0
AND u.status = 8
LEFT JOIN availability a
ON ir.user_id = a.user_id
AND a.date = CURDATE()
WHERE ir.introle = $imarole
AND a.user_id IS NULL /* User does NOT exist in availability table w/ today's date */
EDIT: This second query is based on the comments below, asking to show only users who do exist in the availability table.
SELECT u.*
FROM internalrole ir
INNER JOIN users u
ON ir.user_id = u.id
AND u.archive = 0
AND u.status = 8
INNER JOIN availability a
ON ir.user_id = a.user_id
WHERE ir.introle = $imarole
Hmm, maybe something like this
SELECT * FROM users WHERE id IN (SELECT user_id FROM internalrole WHERE introle = $imarole) AND archive = 0 and status = 8;
A handy thing for me to remember is that tables are essentially arrays in SQL.
HTH!
Nested queries are your friend.
SELECT * FROM users WHERE id in (SELECT user_id FROM internalrole WHERE introle = $imarole) AND archive = 0 and status = 8
Alternatively joins:
SELECT * FROM users INNER JOIN internalrole ON users.id = internalrole.user_id WHERE internalrole.user_id = $imarole AND users.archive = 0 and users.status = 8

Categories