MySQL Query returning blank key - php

I have a MySQL Query which works fine except the field rnd_key is returned as null despite it having values. If I run a normal query without the join then the key is returned.
SELECT *, SUM(time_duration) as total_time
FROM rnd
LEFT JOIN time ON rnd.rnd_key = time.rnd_key
WHERE rnd.rnd_owner = $eng AND rnd.rnd_status != 90
AND (rnd.rnd_status != 80 OR rnd.rnd_status > '".$ninetyDate."')
GROUP BY rnd.rnd_key
Thanks

try two things:
First: try RIGHT JOIN instead of LEFT JOIN.
Second: try to give each of rnd_key columns diffrent alias names. duplicated names may cause such problem

Related

How to use a column as part of mysql query?

Only in a sql query (used in a php script), I need to use the value of a column into the query to optimize the speed but it doesn't work well.
I have mutiple tables so I use JOIN
If I do that :
LEFT JOIN `gestdetails` gd ON gd.id IN (205467,205468,205469)
I works well !
But if I use the value of a column (gc.details = 205467,205468,205469) :
LEFT JOIN `gestdetails` gd ON gd.id IN (gc.details)
It doesn't work, it only use the first value '205467'.
I'm trying to do that to go faster with the query : if I do the classic JOIN on id = id, it also works but it's way too long...
LEFT JOIN `gestdetails` gd ON (gd.idcommande = gc.id)
gestcommandes = table of unique orders
gestdetails = table of multiple products linked to idcommande of gestcommandes
Here is the full query :
SELECT
gc.*,
count(gd.idcommande),
GROUP_CONCAT(CONCAT(gd.id,"#",gd.idcommande,"#",gd.ref,"#",gd.poids,"#",gd.numcolis,"#",gd.designation,"#",gd.prix) SEPARATOR "|"),
ad.*
FROM
`gestcommandes` gc
LEFT JOIN `gestdetails` gd ON gd.id IN (gc.details)
LEFT JOIN `adresses` ad ON ad.id_commande = gc.id
WHERE
`mp` LIKE '%-eb' AND (`statut` = 5 OR `statut` = 6) AND `date_expe` >= '2020-04-07 00:00:00' AND `date_expe` <= '2020-04-07 23:59:59'
AND
ad.is_delivery = 1
GROUP BY
gc.id
Executing this query, it only uses the first number into the gc.details column (i.e '205467' from '205467,205468,205469' and of course, I've got warnings :
Warning: #1292 Truncated incorrect INTEGER value: '205467,205468,205469'
gc.details can count 1 to 100 numbers...
I tryed so many things, I don't manage to do it, so if anybody can help me (without creating procedure)... thank you !
ps : the "GROUP_CONCAT" part works well... if I manage to get more than 1 result for the details...

#variable mysql return null value on php mysql execution

I have this mysql need to run in php:
$sql_subject_summary = "SELECT
c.subject_code_id, c.subject_name, #total_target:= SUM(s.total_target_question) AS total_target_question,
#total_correct := ROUND((RAND() * (#total_target-10))+10) AS total_correct,
(#total_correct / #total_target)*100 AS percent, c.icon_filename
FROM
edu_subject_code c LEFT JOIN wkp_wg_student_subject s ON c.subject_code_id=s.subject_code_id
WHERE s.student_id=$student_id AND s.week_id = $current_week_id
$sql_inject
GROUP BY s.subject_code_id ";
However, the values of #total_correct, #total_target return null on php mysql execution .
When I run in mysql IDE, then the result is ok.
How to solve this problem?
That's right cause for that to work you need to use SELECT INTO... construct like select col1 into #arg1 from tbl1. Moreover since you are running the query from PHP why you need that at all? if you really need that then consider wrapping the query in a stored procedure and have those parameter as OUT parameter.
Well it's return null cause you are not selecting those parameter. After your query executes, you need to select those parameter saying select #total_correct, #total_target;.
Why don't you just run the query as is (like below) and fetch the specific columns value
SELECT
c.subject_code_id, c.subject_name, SUM(s.total_target_question) AS total_target_question,
ROUND((RAND() * (#total_target-10))+10) AS total_correct,
(#total_correct / #total_target)*100 AS percent, c.icon_filename
FROM
edu_subject_code c LEFT JOIN wkp_wg_student_subject s ON c.subject_code_id=s.subject_code_id
WHERE s.student_id=$student_id AND s.week_id = $current_week_id
$sql_inject
GROUP BY s.subject_code_id

Weird MYSQL results using PDO::FETCH_ASSOC without column alias

I have a simple left join query.
SELECT e.employee_id as employee
, e.badge_id as badge
, e.first_nm as first
, e.last_nm as last
, e.work_phone as work_ph
, e.mobile_phone as mobile_ph
, e.manager_id as man_id
, e.title_id as titl_id
, e.username as user
, e.start_dt as start
, m.employee_id as memp_id
, m.last_nm as m_last
, m.first_nm as m_first
, t.title_nm as titl_nm
FROM employee e
left join employee m
on e.manager_id = m.employee_id
left join title t
on e.title_id = t.title_id
WHERE e.employee_id = 1
If I use column aliases as I have done above, the query works fine. If I do not use aliases, however, some values do not get returned. For example, the following returns a space if I do not give the column an alias.
e.first_nm as first //returns "Robert"
e.first_nm //returns ""
e.first_nm as first_nm //returns "" (alias matches column name)
In this same query,
e.middle_nm //will return "P"
regardless of whether it has an alias or not. I'm baffled.
I have given my tables aliases and I have used the table alias in the column names so there shouldn't be any ambiguous column names.
Any thoughts would be appreciated.
Thanks,
Rob
You have two columns with same name as first_nm and problably the PDO donĀ“t know what return to your code then return simple "". Although they are in diferent tables when came to a record they have the same name... you see the problem?
You have two columns with same name as first_nm and mysql knows how to return them all right, and then return simple "first_nm" for both. And then PDO have to assign them to array members, making field names as array keys. There is only one way, like this
$row['first_nm'] = first col;
$row['first_nm'] = second col;
If you try to see into $row, how many entries you will find?
So, you either have to use FETCH_ROW or give your fields distinct names. It's neither mysql nor PDO to blame - it's just how the things work.

GROUP_CONCAT strange result

I try to use group_concat to create more quickly xml outpout.
The record number is different between traditional query. Indeed, when my query use group concat, I have less record.
SELECT GROUP_CONCAT(
CONCAT('\n<p>\n',
CONCAT('\n<id>',paIndex,'</id>\n'),
CONCAT('<prInitiales>',prInitiales,'</prInitiales>\n'),
CONCAT('<paNomPren>',paNomPrenom,'\n',ttT_Traitement_P,'</paNomPren>\n'),
CONCAT('<ttTStatutP>',ttTStatutP,' - ',DATE_FORMAT(ttDateStatut,'%d/%m/%Y'),'\n',ttUserImportant,'</ttTStatutP>\n'),
CONCAT('<paDossier1>',paDossier1,'\n',paDossier2,'</paDossier1>\n'),
CONCAT('<paNumTel1>',paNumTel1,'\n',paNumTel2,'</paNumTel1>\n'),
CONCAT('<paNaissanceS>',DATE_FORMAT(paNaissance,'%d/%m/%Y'),'</paNaissanceS>\n'),
'</p>') ORDER BY paNomPrenom DESC) AS xml
FROM 20Patients_1012
JOIN 30Traitemnt_201223 ON 20Patients_1012.paIndex = 30Traitemnt_201223.ttIndex
JOIN 12Praticien_02 ON 30Traitemnt_201223.ttPraticien = 12Praticien_02.prIndex
The traditional query:
SELECT 20Patients_1012.paIndex, 20Patients_1012.paNomPrenom, 20Patients_1012.paDossier1, 20Patients_1012.paDossier2, 20Patients_1012.paNaissance, 20Patients_1012.paNumTel1, 30Traitemnt_201223.ttTStatutP, 30Traitemnt_201223.ttDateStatut, 12Praticien_02.prInitiales
FROM 20Patients_1012
JOIN 30Traitemnt_201223 ON 20Patients_1012.paIndex = 30Traitemnt_201223.ttIndex
JOIN 12Praticien_02 ON 30Traitemnt_201223.ttPraticien = 12Praticien_02.prIndex ORDER BY 20Patients_1012.paNomPrenom ASC
Thanks for helping
As stated in the manual:
The result is truncated to the maximum length that is given by the group_concat_max_len system variable, which has a default value of 1024. The value can be set higher, although the effective maximum length of the return value is constrained by the value of max_allowed_packet. The syntax to change the value of group_concat_max_len at runtime is as follows, where val is an unsigned integer:
SET [GLOBAL | SESSION] group_concat_max_len = val;
You used LEFT JOIN in a query and simple JOIN in the other. This may lead to different results because LEFT JOIN also consider records that do not have a match in the other table.
I found the solution.
Indeed, if null value, record is ignored, so I use, COALESCE function to solve that!

How to return multiple rows in a LEFT JOIN

I have a situation where lets say i'm trying to get the information about some food. Then I need to display all the information plus all the ingredients in that food.
With my query, i'm getting all the information in an array but only the first ingredient...
myFoodsArr =
[0]
foodDescription = "the description text will be here"
ratingAverage = 0
foodId = 4
ingredient = 1
ingAmount = 2
foodName = "Awesome Food name"
typeOfFood = 6
votes = 0
I would like to get something back like this...
myFoodsArr =
[0]
foodDescription = "the description text will be here"
ratingAverage = 0
foodId = 4
ingArr = {ingredient: 1, ingAmount: 4}, {ingredient: 3, ingAmount: 2}, {ingredient: 5, ingAmount: 1}
foodName = "Awesome Food name"
typeOfFood = 6
votes = 0
This is the query im working with right now. How can I adjust this to return the food ID 4 and then also get ALL the ingredients for that food? All while at the same time doing other things like getting the average rating of that food?
Thanks!
SELECT a.foodId, a.foodName, a.foodDescription, a.typeOfFood, c.ingredient, c.ingAmount, AVG(b.foodRating) AS ratingAverage, COUNT(b.foodId) as tvotes
FROM `foods` a
LEFT JOIN `foods_ratings` b
ON a.foodId = b.foodId
LEFT JOIN `foods_ing` c
ON a.foodId=c.foodId
WHERE a.foodId=4
EDIT:
Catcall introduced this concept of "sub queries" I never heard of, so I'm trying to make that work to see if i can do this in 1 query easily. But i just keep getting a return false. This is what I was trying with no luck..
//I changed some of the column names to help them be more distinct in this example
SELECT a.foodId, a.foodName, a.foodDescription, a.typeOfFood, AVG(b.foodRating) AS ratingAverage, COUNT(b.foodId) as tvotes
FROM foods a
LEFT JOIN foods_ratings b ON a.foodId = b.foodId
LEFT JOIN (SELECT fId, ingredientId, ingAmount
FROM foods_ing
WHERE fId = 4
GROUP BY fId) c ON a.foodId = c.fId
WHERE a.foodId = 4";
EDIT 1 more thing related to ROLANDS GROUP_CONCAT/JSON Idea as a solution 4 this
I'm trying to make sure the JSON string im sending back to my Flash project is ready to be properly parsed Invalid JSON parse input. keeps popping up..
so im thinking i need to properly have all the double quotes in the right places.
But in my MySQL query string, im trying to escape the double quotes, but then it makes my mySQL vars not work, for example...
If i do this..
GROUP_CONCAT('{\"ingredient\":', \"c.ingredient\", ',\"ingAmount\":', \"c.ingAmount\", '}')`
I get this...
{"ingredient":c.ingredient,"ingAmount":c.ingAmount},{"ingredient":c.ingredient,"ingAmount":c.ingAmount},{"ingredient":c.ingredient,"ingAmount":c.ingAmount}
How can i use all the double quotes to make the JSON properly formed without breaking the mysql?
This should do the trick:
SELECT food_ingredients.foodId
, food_ingredients.foodName
, food_ingredients.foodDescription
, food_ingredients.typeOfFood
, food_ingredients.ingredients
, AVG(food_ratings.food_rating) food_rating
, COUNT(food_ratings.foodId) number_of_votes
FROM (
SELECT a.foodId
, a.foodName
, a.foodDescription
, a.typeOfFood
, GROUP_CONCAT(
'{ingredient:', c.ingredient,
, ',ingAmount:', c.ingAmount, '}'
) ingredients
FROM foods a
LEFT JOIN foods_ing c
ON a.foodsId = c.foodsId
WHERE a.foodsId=4
GROUP BY a.foodId
) food_ingredients
LEFT JOIN food_ratings
ON food_ingredients.foodId = food_ratings.foodId
GROUP BY food_ingredients.foodId
Note that the type of query you want to do is not trivial in any SQL-based database.
The main problem is that you have one master (food) with two details (ingredients and ratings). Because those details are not related to each other (other than to the master) they form a cartesian product with each other (bound only by their relationship to the master).
The query above solves that by doing it in 2 steps: first, join to the first detail (ingredients) and aggregate the detail (using group_concat to make one single row of all related ingredient rows), then join that result to the second detail (ratings) and aggregate again.
In the example above, the ingredients are returned in a structured string, exactly like it appeared in your example. If you want to access the data inside PHP, you might consider adding a bit more syntax to make it a valid JSON string so you can decode it into an array using the php function json_decode(): http://www.php.net/manual/en/function.json-decode.php
To do that, simply change the line to:
CONCAT(
'['
, GROUP_CONCAT(
'{"ingredient":', c.ingredient
, ',"ingAmount":', c.ingAmount, '}'
)
, ']'
)
(this assumes ingredient and ingAmount are numeric; if they are strings, you should double quote them, and escape any double quotes that appear within the string values)
The concatenation of ingredients with GROUP_CONCAT can lead to problems if you keep a default setting for the group_concat_max_len server variable. A trivial way to mitigate that problem is to set it to the maximum theoretical size of any result:
SET group_concat_max_len = ##max_allowed_packet;
You can either execute this once after you open the connection to mysql, and it will then be in effect for the duration of that session. Alternatively, if you have the super privilege, you can change the value across the board for the entire MySQL instance:
SET GLOBAL group_concat_max_len = ##max_allowed_packet;
You can also add a line to your my.cnf or my.ini to set group_concat_max_lenght to some arbitrary large enough static value. See http://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_group_concat_max_len
One obvious solution is to actually perform two queries:
1) get the food
SELECT a.foodId, a.foodName, a.foodDescription, a.typeOfFood
FROM `foods` a
WHERE a.foodsId=4
2) get all of its ingredients
SELECT c.ingredient, c.ingAmount
FROM `foods_ing` c
WHERE c.foodsId=4
This approach has the advantage that you don't duplicate data from the "foods" table into the result. The disadvantage is that you have to perform two queries. Actually you have to perform one extra query for each "food", so if you want to have a listing of foods with all their ingredients, you would have to do a query for each of the food record.
Other solutions usually have many disadvantages, one of them is using GROUP_CONCAT function, but it has a tough limit on the length of the returned string.
When you compare MySQL's aggregate functions and GROUP BY behavior to SQL standards, you have to conclude that they're simply broken. You can do what you want in a single query, but instead of joining directly to the table of ratings, you need to join on a query that returns the results of the aggregate functions. Something along these lines should work.
select a.foodId, a.foodName, a.foodDescription, a.typeOfFood,
c.ingredient, c.ingAmount,
b.numRatings, b.avgRating
from foods a
left join (select foodId, count(foodId) numRatings, avg(foodRating) avgRating
from foods_ratings
group by foodId) b on a.foodId = b.foodId
left join foods_ing c on a.foodId = c.foodId
order by a.foodId

Categories