Count results in left join? - php

trying to make the move to MySQLi and some of it is baffling me. Quick question as my query is currently saying there's 1 result even if there isn't one...
How do I go about finding the number of rows returned for this:
$sql = <<<SQL
SELECT u.*, t.*
FROM Users u
LEFT JOIN Transactions t USING (UserID)
WHERE UserID = $UserID
ORDER BY Date DESC
LIMIT 5
SQL;
Presently it is returning 1 result from an empty table with all the values being null.

You should try to place the value instead of $UserID. Then, you should try to run this query in MySQL.
Also, check your code which processes query results.

The reason I was getting results when there weren't any was because of using Left Join which nulls any results that don't match. as was pointed out in comments. I needed Inner Join instead, which is working as required.

Related

SQL Inner Join query doesn't return all records, but instead the first one ever made

SELECT user.name, comments.cdata, comments.likes FROM comments
WHERE pid = $postNum
INNER JOIN user ON comments.uid = user.uid
ORDER BY cdate
Quick Notes:
I am a beginner, please don't be rude to me, I am trying to learn more
Yes, I have tried LEFT JOIN, but that just returns an SQL sintax error
My database is like this:
2 tables, 1 one is comments, comments has comments.cdata, comments.likes and comments.uid, the user one has the name of the user.
What I have been trying to accomplish is getting the name of the user with the comment data, instead of UID and comment data.
I also can not use 2 queries, due to me getting all the records and then displaying them on page via PHP for each.
Your query is syntactically incorrect. JOIN is an operator in the FROM clause. WHERE is a clause that follows the FROM clause.
In addition, I think the cdata and cdate should be the same thing, although I don't know what.
I also recommend using table aliases. So:
SELECT u.name, c.cdata, c.likes
FROM comments c JOIN
user u
ON c.uid = u.uid
WHERE c.pid = $postNum
ORDER BY c.cdata

MySQL GROUP BY taking so much time to fetch records

I want to query the database to fetch the last visit time of every user here is the query:
SELECT
u.user_id,
u.firstname,
u.lastname,
u.email,
pv.visit_time
FROM
users u
LEFT OUTER JOIN pageviews pv
ON u.user_id = pv.user_id
GROUP BY pv.user_id
LIMIT 0, 12
This query is taking 30 to 40 seconds to execute on live server, however if i remove the GROUP BY clause then it is taking 3 to 6 seconds but with duplicate records. Any idea what's wrong with this query?
Also i have tried DISTINCT but found same issue.
Thanks, any help would be appreciated.
What are your indexes?
Do you really want a left join, as that would seem irrelevant? Using a LEFT OUTER JOIN it would just seem that you are going to get a row for user_id of NULL, but with nulls also in the other columns.
Further you are using GROUP BY to return a single row for each user. However which row is returned is not defined, so it could be any page views visit_time that is brought back for a user.
Also you have only a single column in the GROUP BY clause but other non aggregate columns in the select. With default options in MySQL this will work but will not work in most flavours of SQL and will also not work when MySQL is performing the group by in strict mode (see this manual page ).
Add a index on u.user_id and a compound index on pv.user_id AND pv.visit_time. Then assuming you want the latest visit time for each user try the query as:-
SELECT u.user_id,
u.firstname,
u.lastname,
u.email,
MAX(pv.visit_time)
FROM users u
INNER JOIN pageviews pv
ON u.user_id = pv.user_id
GROUP BY u.user_id, u.firstname, u.lastname, u.email
ORDER BY u.user_id
LIMIT 0, 12
(strictly speaking the ORDER BY clause is not required as it is implicitly done by the GROUP BY clause, but it does make it more explicit what is expected to anyone reading the code in future).
The group by clause and distinct requires a full scan of the table.
Maybe the query without the group by clause can be faster in returning the first rows, have you checked how long it takes to retrieve the whole result set?
If it takes only 3-6 seconds, I would refresh the statistics, maybe the optimiser is not doing the best choices for the join (I imagine that the table pageviews is a large one).
Select t1.x, t1.y, t1.z from table1 t1 Group by t1.x,t1.y,t1.z....
It will give better performance dude...
Group by fields (x,y,z) should be appended with select statement to get better performance..
Try it ...(group by operation will happen with in result set for above query)

Type of Mysql Join to remove from query list

I have 3 three tables: a, aLocale, aCompany.
I need to get all the rows where a.id = aLocale.parentID if aCompany.parentID does not exist.
I know that aLocale would be an innerJoin but what about aCompany?
I could also be looking at the problem wrong. The only reason I am using aCompany is if matching row doesn't exist. Currently, I am running a query for a and getting the results as an array. I then iterate through the array and unset the items that match a separate query of aCompany. I feel there would be a better way of doing it with 1 query.
You may use LEFT JOIN instead of INNER JOIN, this will return even non matching values
SELECT * FROM a INNER JOIN aLocale ON a.id = alocale.parentID
LEFT JOIN aCompany ON aCompany.parentID = alocale.parentID
WHERE aCompany.parentID IS NULL
Edited:
You can also get parentID not null using coalesce() instead of * in your select
SELECT COALESCE(aCompany.parentID, aLocale.parentID) AS parentID FROM ....
Using coalesce() you'll find the first not null value among arguments list

SUM value from query changes when i add inner join to the query

$sql = mysql_query("SELECT totals.*, sum(totals.payments) as total_payments
FROM totals
INNER JOIN users
GROUP BY totals.idseller;");
When i add the INNER JOIN the sum value is changed. Why?
In my SQL table i have one record in totals width this value: 8943.09 but when i do the some the result is giving me this value: 44715.45
What i am doing wrong?
$sql = mysql_query("SELECT totals.*, sum(totals.payments) as total_payments FROM totals
INNER JOIN users ON totals.idseller = users.idseller
GROUP BY users.UserName;");
Use this Hope this will help you.
When you INNER JOIN to another table, the returned data set is modified to only include rows that exist in both tables. In this case it is likely that there are rows in 'totals' that do not have a matching row in users - either the totals.idseller field might accept null values, or data has become orphaned when matching users have been deleted or edited.
If you want all data in 'totals' regardless of matching user you would user a LEFT JOIN instead in ms-sql, I suspect a similar approach will work in my-sql
You should give an "on" based on the ids. Such as like
inner join users on users.id = totals.idseller
Otherways the sql server will combine all possible rows in the tables, which is most cases not what you wish.
Because when you are adding inner join in your SQL Query, it means you are selecting the data which is common in both the tables.
EX:
SELECT * FROM TABLE_A
INNER JOIN TABLE_B
ON TABLE_A.ID = TABLE_B.ID
If you are joining users table which contains 5 records. By joining table, as there is no any column mapping, this sum-up 5 times and this is reason for showing different values.
Please let me know something wrong in it.
Thanks,
Umehs

I dont know whats wrong with my SQL join, Its my fisrt time using it

Ok, I have this code, I dont have error.... i have just nothing.... nothing apears:
$idea = $bdd->query("SELECT * FROM ideas
INNER JOIN follow ON ideas.idcreador=follow.idseguidor
WHERE follow.idseguidor ='".$_SESSION['userid']."' ORDER BY id DESC");
while($datoideaperfil2 = $idea->fetch())
{
echo $datoideaperfil2['ideas.idcreador'] <br />;
}
What is wrong? Help me please its my fist time with SQL Joins...
Thanks
There doesn't appear to be anything wrong with the SQL itself, but one thing that I do suspect is that you have a column called id in both tables. If you don't use an alias, then mysql won't know what to order by and return an error.
Try this:
SELECT
*
FROM
ideas
INNER JOIN follow
ON ideas.idcreador=follow.idseguidor
WHERE
follow.idseguidor ='".$_SESSION['userid']."'
ORDER BY
follow.id DESC
To understand what's wrong with the query you need to understand how joins in SQL work. A JOIN results in a "table" where for every row in table A, you get a resulting row that is combined with every row in table B. So if table A has 5 rows, and table B has 10 rows, you get 50 (5x10) rows, which you need to filter with your WHERE clause.
Results also differ, and in your case this is the important part, wether you go for an INNER JOIN or an OUTER JOIN. An INNER JOIN's resulting "table", ONLY contains rows where the rows from table A and table B match the ON clause. So if you have a row in table ideas, which has no relation to any rows in table follow, it won't show up in the results. Would you choose an OUTER JOIN (a LEFT or RIGHT OUTER JOIN) any non-matching row will show up, but the row's values will be set to NULL for whatever values it could not find a relation for.
Since you chose an INNER JOIN, and you get no results, I'm guessing you have no relations between any rows.
What's also important is that you specify what table you want the ORDER BY clause to be ordered by, or you get an ambigious column exception (if both tables have a column named id).
you have used a INNER JOIN which will only display data if both tables have corresponding rows. Try using a LEFT or RIGHT join.

Categories