Why isn't my SQL LEFT JOIN query working? - mysql

It is returning 0 rows when there should be some results.
This is my first attempt at using JOIN but from what I've read this looks pretty much right, right?
"SELECT pending.paymentid, pending.date, pending.ip, pending.payer, pending.type, pending.amount, pending.method, pending.institution, payment.number, _uploads_log.log_filename
FROM pending
LEFT JOIN _uploads_log
ON pending.paymentid='".$_GET['vnum']."'
AND _uploads_log.linkid = pending.paymentid"
I need to return the specified values from each table where both pending.paymentid and _uploads_log.log_filename are equal to $_GET['vnum]
What is the correct way to do this? Why am I not getting any results?
If someone more experienced than me could point me in the right direction I would be much obliged.
EDIT
For pending the primary key is paymentid, for _uploads_log the primary is a col called log_id and log_filename is listed as index.

Try this
SELECT pending.paymentid,
pending.date,
pending.ip,
pending.payer,
pending.type,
pending.amount,
pending.method,
pending.institution,
payment.number,
_uploads_log.log_filename
FROM pending
LEFT JOIN _uploads_log
ON _uploads_log.linkid = pending.paymentid
WHERE _uploads_log.log_filename = '" . $_GET['vnum'] . "'
Your current query is vulnerable with SQL Injection. Please take time to read the article below.
Best way to prevent SQL injection in PHP?

The ON clause only should have the condition to link the two tables especially if it is LEFT JOIN. The WHERE clause then has the actual condition. Otherwise you will get nothing if there is no corresponding entry in _uploads_log. It also is more easy to read in my opinion.
As another remark. It is always better to work with bind parameters to avoid SQL injection.

Related

When can I say that it's the best-optimized query?

I tried to optimize a query, but it still a tad bit slow. Here, EXPLAIN statement data for reference. Also adding an execution and evaluation cost information JSON. Can you tell me if I can improve something? Or it's the best that I can do.
Exaplain.json
EDIT
What I really want to know is, a way to know that the query is fully optimized and I should start looking somewhere else.
Anyways, please tell me for this query and I will learn something more. Adding the query and a diagram of the table structure.
SELECT o.object, b.baseline, s.testType, ut.suite,
JSON_EXTRACT(ut.failTestsData, '$.failButBaselinePassesTests[*]',
'$.baselineDataNotAvailableTests[*]',
'$.failDifferentThanBaselineTests[*]') AS failTests FROM objects as o
LEFT JOIN baselines as b ON b.baselineID = o.baselineID
LEFT JOIN instances AS i ON o.objectID = i.objectID
LEFT JOIN buildOSs as os ON i.osID = os.osID
LEFT JOIN unittestsdetails AS ut ON ut.instanceID = i.instanceID
LEFT JOIN suites AS s ON s.suiteID = ut.suiteID
WHERE o.objectID IN ( 20836, 20210, 20201, 20202, 20370, 21138, 20731,
22242, 21168, 21476, 23384, 22043, 20548, 20289, 20777, 21324, 20545,
20682, 20266, 21184, 21202, 20741, 20918, 20261, 20516, 20291, 20619,
21438, 20351, 22047, 20264, 20265, 21181, 20988, 20842, 21429, 20643,
20570, 20775, 21904, 20923........... )
If you need something else please let me know.
a way to know that the query is fully optimized and I should start looking somewhere else
This doesn't really exist, for a simple reason : if your query is a "bit" complex, depending on the data in your table, what is "fully optimized" may turn to be a pretty bad choice.
Working on a single line vs some thousand of thousand is not the same.
For less complex query, I'll say : if every WHERE and JOIN clause use an index, then you're probably as close as "optimized" you can (maybe function based index and different kind of index, but that's it).
Looking at your query is seem you're already done ;)

Why is my query wrong?

before i use alias for table i get the error:
: Integrity constraint violation: 1052 Column 'id' in field list is ambiguous
Then i used aliases and i get this error:
unknown index a
I am trying to get a list of category name ( dependant to a translation) and the associated category id which is unique. Since i need to put them in a select, i see that i should use the lists.
$categorie= DB::table('cat as a')
->join('campo_cat as c','c.id_cat','=','a.id')
->join('campo as d','d.id','=','c.id_campo')
->join('cat_nome as nome','nome.id_cat','=','a.id')
->join('lingua','nome.id_lingua','=','lingua.id')
->where('lingua.lingua','=','it-IT')
->groupby('nome.nome')
->lists('nome.nome','a.id');
The best way to debug your query is to look at the raw query Laravel generates and trying to run this raw query in your favorite SQL tool (Navicat, MySQL cli tool...), so you can dump it to log using:
DB::listen(function($sql, $bindings, $time) {
Log::info($sql);
Log::info($bindings);
});
Doing that with yours I could see at least one problem:
->where('lingua.lingua','=','it-IT')
Must be changed to
->where('lingua.lingua','=',"'it-IT'")
As #jmail said, you didn't really describe the problem very well, just what you ended up doing to get around (part of) it. However, if I read your question right you're saying that originally you did it without all the aliases you got the 'ambiguous' error.
So let me explain that first: this would happen, because there are many parts of that query that use id rather than a qualified table`.`id.
if you think about it, without aliases you query looks a bit like this: SELECT * FROM `cat` JOIN `campo_cat` ON `id_cat` = `id` JOIN `campo` ON `id` = `id_campo`; and suddenly, MySQL doesn't know to which table all these id columns refer. So to get around that all you need to do is namespace your fields (i.e. use ... JOIN `campo` ON `campo`.`id` = `campo_cat`.`id_campo`...). In your case you've gone one step further and aliased your tables. This certianly makes the query a little simpler, though you don't need to actually do it.
So on to your next issue - this will be a Laravel error. And presumably happening because your key column from lists($valueColumn, $keyColumn) isn't found in the results. This is because you're referring to the cat.id column (okay in your aliased case a.id) in part of the code that's no longer in MySQL - the lists() method is actually run in PHP after Laravel gets the results from the database. As such, there's no such column called a.id. It's likely it'll be called id, but because you don't request it specifically, you may find that the ambiguous issue is back. My suggestion would be to select it specifically and alias the column. Try something like the below:
$categories = DB::table('cat as a')
->join('campo_cat as c','c.id_cat','=','a.id')
->join('campo as d','d.id','=','c.id_campo')
->join('cat_nome as nome','nome.id_cat','=','a.id')
->join('lingua','nome.id_lingua','=','lingua.id')
->where('lingua.lingua','=','it-IT')
->groupby('nome.nome')
->select('nome.nome as nome_nome','a.id as a_id') // here we alias `.id as a_id
->lists('nome_nome','a_id'); // here we refer to the actual columns
It may not work perfectly (I don't use ->select() so don't know whether you pass an array or multiple parameters, also you may need DB::raw() wrapping each one in order to do the aliasing) but hopefully you get my meaning and can get it working.

LEFT JOIN breaks WHERE Clause

I've recently been required to input more information from my database and I've just LEFT JOIN to help me, it works almost perfectly(it does actually get the right field from the other table) but my WHERE clause is nullified giving the user access to both tables without the restriction of my where clause.
MySQL doesn't crap out any errors, so I'm assuming it's something to do with my where clause or something happened in the join.
SELECT * FROM students
LEFT JOIN courses ON students.appliedforCourse = courses.idNumber
WHERE
students.telephone LIKE '%$var'
OR students.email LIKE '%$var'
OR students.address like'%$var%'
OR (CONCAT(students.firstName,' ',students.lastName) LIKE '%$var%')
AND addedBy ='$userid'
LIMIT $s,limit
The query itself is correct (although really inefficient due to ORs and % % [ indexes will not be used] ).
I would suggest to echo the query, are you sure that $var is evaluated correctly ? Try to run the query directly in mysql (via phpmyadmin for example or using console).
I suspect that simply you did not set $var value. Then condition e.g. students.telephone LIKE '%$var' will become students.telephone LIKE '%' (always true for not null address), which will match every record of the join , exactly what you are getting.

PHP Heatmap - Large Value difference

Hi I have this Query and I'm getting an empty result, Anyone see anything obviously wrong with this?
SET SQL_BIG_SELECTS=1;
SELECT sector, SUM((fleetnow)+(fleetsoon)) AS Count
FROM AEDatabase
INNER JOIN AEPlayer AS Own ON AEDatabase.owner = Own.id
INNER JOIN AEPlayer AS Occ ON AEDatabase.occer = Occ.id
WHERE Galaxy='L49' AND (Own.guild='1085' OR Occ.guild='1085')
GROUP BY sector
Specific message from MySQL is:
"MySQL returned an empty result set (i.e. zero rows). ( Query took 0.4441 sec )"
Thanks for any help anyone can give.
If SQL request is composed correctly according to your business logic, and it returns no data it means, that either AEPlayer doesn't contain related data or AEDatabase doesn't contain any data related to Galaxy='L49'
You should separate all components of your request to determine what exactly collapses the result set.

mysql to codeigniter active record help

Active record is a neet concept but sometimes I find it difficult to get more complicated queries to work. I find this is at least one place the CI docs are lacking.
Anyway,
This is the sql I wrote. It returns the expected results of quests not yet completed by the user that are unlocked and within the users level requirements:
SELECT writing_quests . *
FROM `writing_quests`
LEFT OUTER JOIN members_quests_completed ON members_quests_completed.quest_id = writing_quests.id
LEFT OUTER JOIN members ON members.id = $user_id
WHERE writing_quests.unlocked =1
AND writing_quests.level_required <= $userlevel
AND members_quests_completed.user_id IS NULL
This is the codeigniter active record query, it returns all quests that are unlocked and within the users level requirement:
$this->db->select('writing_quests.*');
$this->db->from('writing_quests');
$this->db->join('members_quests_completed', 'members_quests_completed.quest_id = writing_quests.id', 'left outer');
$this->db->join('members', "members.id = $user_id", 'left outer');
$this->db->where('writing_quests.unlock', 1);
$this->db->where('writing_quests.level_required <=', $userlevel);
$this->db->where('members_quests_completed.user_id is null', null, true);
I'm guessing there is something wrong with the way I am asking for Nulls. To be thorough, I figured I'd include everything.
I agree that sometimes CI active record can overcomplicate things. Try this for your IS NULL where clause:
$this->db->where('members_quests_completed.user_id IS ','NULL',false);
Try also to enable the profiler or echo the generated query with:
echo $this->db->last_query();
That might shed some light on what the issue is.
Sometimes CI makes it a bit complicated... you can always use $this->db->query("your very long query") to simplify a bit (if I recall correctly strings are still escaped - not sure). It's a personal opinion.
$this->db->where('column IS NOT NULL')
in your case
$this->db->where('members_quests_completed.user_id is not null');