MySQL error code needed - php

MySQL always sends a "default response" even when the data doesn't match the query!
How can I design my query to get an error code from MySQL if no data is matching the query?
I need an error code from MySQL to create a 404 or 410 page.
SELECT
place.ID AS id,
place.latitude AS lat,
place.longitude AS lng,
IF(
place.translationID IS NULL,
place.name,
placel10n.text
) AS cityname,
IF(
admcode.translationID IS NULL,
'',
statel10n.text
) AS statename,
IF (
countrycode.translationID IS NULL,
countrycode.name,
countryl10n.Text
) AS countryname,
IF(
place.textID IS NULL,
'',
`l10n-strings`.text
) AS description
FROM
places AS place
LEFT JOIN `l10n-strings` AS placel10n ON (place.translationID = placel10n.translationID AND placel10n.languageCode = 'de')
LEFT JOIN admin1codesascii AS admcode ON (place.admin1 = admcode.statecode AND place.country = admcode.country)
LEFT JOIN `l10n-strings` AS statel10n ON (admcode.translationID = statel10n.translationID AND statel10n.languageCode = 'de')
LEFT JOIN countries AS countrycode ON (place.country = countrycode.iso_alpha2)
LEFT JOIN `l10n-strings` AS countryl10n ON (countrycode.translationID = countryl10n.TranslationID AND countryl10n.LanguageCode = 'de')
LEFT JOIN texts ON (place.textID = texts.id)
LEFT JOIN `l10n-strings` ON (texts.translationID = `l10n-strings`.translationID AND `l10n-strings`.languageCode= 'de')
WHERE
place.id = '8'
AND
place.featurecode = 'A'
OR
place.featurecode = 'AB'
OR
place.featurecode = 'AAC'
LIMIT 0,1
This query always returns a result even when the where statements are wrong.

Yes, that's the way SQL works. If there are no rows that match your query, the result set will be empty. It's the job of the program (written in PHP or what have you) in which your SQL query is embedded to respond to the "no rows" case and change the response status (to 404 or what have you). SQL queries are not responsible for HTTP status codes -- it's chalk and cheese.

In MySQL, AND has higher operator precedence than OR, so the conditions in your WHERE clause will be interpreted as
(place.id = '8' AND place.featurecode = 'A') OR
place.featurecode = 'AB' OR
place.featurecode = 'AAC'
Use parentheses to be explicit about the order of operation you intend. Perhaps you meant this?
place.id = '8' AND
(place.featurecode = 'A' OR
place.featurecode = 'AB' OR
place.featurecode = 'AAC')

Related

PHP query returning only one row out of four

This query was supposed to return me four rows: which are four people with status 50 (which, in the application means "maternity leave"). But it returns only one.
On HeidiSQL the query doesn't even run because it displays a
syntax error on line 13:
(...)
corresponds to your MariaDB server version for the right syntax to use near 'a.id_regiao = '$id_regiao'
AND a.cod_status = 50
AND a.status' at line 13 */"
Here is the query. I'm slowly becoming familiar with sql statements and i did search a lot on SO before asking it:
//SELECTING PROJECT DATA
$query = "SELECT b.id_clt,b.nome AS nome_clt,
a.id_evento AS a_id_evento,a.data AS a_data,a.data_retorno AS a_data_retorno,
c.id_evento AS c_id_evento,c.data AS c_data,c.data_retorno AS c_data_retorno,
(SELECT nome FROM projeto WHERE id_projeto = a.id_projeto) AS nome_projeto,
(SELECT nome FROM curso WHERE id_curso = b.id_curso) AS nome_curso,
DATE_FORMAT(a.data,'%d/%m/%Y') AS a_data_br,
DATE_FORMAT(a.data_retorno,'%d/%m/%Y') AS a_data_retorno_br,
DATE_FORMAT(c.data,'%d/%m/%Y') AS c_data_br,
DATE_FORMAT(c.data_retorno,'%d/%m/%Y') AS c_data_retorno_br
FROM rh_eventos AS a
INNER JOIN rh_clt AS b ON (a.id_clt = b.id_clt AND a.cod_status = 50)
LEFT JOIN rh_eventos AS c ON (b.id_clt = c.id_clt AND c.cod_status = 54)
WHERE $cond_projeto a.id_regiao = '$id_regiao'
AND a.cod_status = 50
AND a.status = 1
AND NOW() BETWEEN a.data AND a.data_retorno
ORDER BY nome_projeto,b.nome;";
The problem is here in the query:
WHERE $cond_projeto a.id_regiao = '$id_regiao'
This inserts a variable (or maybe a full test?) without proper syntax. If it is a variable, include the table's column name in the criterium. If it is a full test, include AND like so:
WHERE $cond_projeto AND a.id_regiao = '$id_regiao'
Beware though! Use prepared statements, your code now appears to be vulnerable to SQL injection attacks (and those are not to be trifled with).
Here is the query, (as seen by using an echo before it) . I can see the output on heidsql now. Now its better for us to check it:
SELECT b.id_clt,b.nome AS nome_clt,
a.id_evento AS a_id_evento,a.data AS a_data,a.data_retorno AS a_data_retorno,
c.id_evento AS c_id_evento,c.data AS c_data,c.data_retorno AS c_data_retorno,
(SELECT nome FROM projeto WHERE id_projeto = a.id_projeto) AS nome_projeto,
(SELECT nome FROM curso WHERE id_curso = b.id_curso) AS nome_curso,
DATE_FORMAT(a.data,'%d/%m/%Y') AS a_data_br,
DATE_FORMAT(a.data_retorno,'%d/%m/%Y') AS a_data_retorno_br,
DATE_FORMAT(c.data,'%d/%m/%Y') AS c_data_br,
DATE_FORMAT(c.data_retorno,'%d/%m/%Y') AS c_data_retorno_br
FROM rh_eventos AS a
INNER JOIN rh_clt AS b ON (a.id_clt = b.id_clt AND a.cod_status = 50)
LEFT JOIN rh_eventos AS c ON (b.id_clt = c.id_clt AND c.cod_status = 54)
WHERE a.id_regiao = '1' AND a.cod_status = 50
AND a.status = 1
AND NOW() BETWEEN a.data AND a.data_retorno ORDER BY nome_projeto,b.nome;
I can now see the output on heidsql, though i still cant figure out why it doesent bring the other thre rows.

Multiple where conditions using OR

I am having an issue with my SQL code.
I need to test multiple conditions against different columns where the inputs are optional. Currently the code will not execute unless both input fields have values. My code is below:
if((empty($fname) === false or empty($lname) === false) && $date1 == null && $date2 == null)
{
$result = mysqli_query($con,"SELECT u.FirstName AS 'First Name', u.LastName AS 'Last Name' , CAST(n.CreatedOn AS date) AS 'Date' , s.SportName AS 'Sport', n.DocumentID AS 'Document ID', n.DocumentName AS 'PDF'
FROM users u
INNER JOIN ncaadocuments n
ON u.UserID = n.UserID
INNER JOIN userathletes a
ON n.UserID = a.UserID
INNER JOIN sport s
ON a.SportID = s.SportID
WHERE n.SchoolID = ('$current_user->ID') AND
(u.FirstName LIKE '%$fname%' OR
u.LastName LIKE '%$lname%')
GROUP BY u.LastName
ORDER BY n.CreatedOn");
echo $fname;
echo $lname;
show_results($result);
}
One of the tricks I've used in the past is to write my where clauses like this:
WHERE (myColumn = #neededVal or #neededVal is null)
and (secondColumn = #anotherVal or #anotherVal is null)
... you'll need to make sure you're not going to be taking a performance hit - sometimes the SQL engine doesn't do the best with this sort of formulation (IIRC.)
But this'll get you where you need to go. If the value is filled out, it'll filter down on the value; if it's not filled out, the condition will always be true.

mysql query is taking long time

my below query is taking more then 10 seconds. How I can optimize this query. Please suggest which field to add index.
This query is drupal view for distance search.
SELECT DISTINCT location.lid AS location_lid, node.nid AS nid, location.name AS location_name, location_phone.phone AS location_phone_phone, location_fax.fax AS location_fax_fax, node.title AS node_title, node.language AS node_language, location.additional AS location_additional, location.city AS location_city, location.latitude AS location_latitude, location.longitude AS location_longitude, location.country AS location_country, location.postal_code AS location_postal_code, location.province AS location_province, location.street AS location_street, field_data_field_showroom_level.field_showroom_level_value AS field_data_field_showroom_level_field_showroom_level_value, field_data_field_showroom_type.field_showroom_type_value AS field_data_field_showroom_type_field_showroom_type_value, field_data_field_showroom_inventory_records.field_showroom_inventory_records_value AS field_data_field_showroom_inventory_records_field_showroom_i, field_data_field_record_type_id.field_record_type_id_value AS field_data_field_record_type_id_field_record_type_id_value, field_data_field_toto_gallery.field_toto_gallery_value AS field_data_field_toto_gallery_field_toto_gallery_value, 'node' AS field_data_field_showroom_location_node_entity_type, 'node' AS field_data_field_day_of_operation_node_entity_type, 'node' AS field_data_field_day_of_operation_comments_node_entity_type, 'node' AS field_data_field_showroom_open_node_entity_type, 'node' AS field_data_field_showroom_close_node_entity_type, 'node' AS field_data_field_appointment_needed_node_entity_type, (COALESCE(ACOS(0.83308162381476*COS(RADIANS(location.latitude))*(0.098658826854837*COS(RADIANS(location.longitude)) + -0.99512131716873*SIN(RADIANS(location.longitude))) + 0.55315007734083*SIN(RADIANS(location.latitude))), 0.00000)*6371570.9190939) AS location_distance, 'node' AS field_data_field_salesforce_id_node_entity_type, 'node' AS field_data_field_multiple_product_sku_node_entity_type, 'node' AS field_data_field_product_types_node_entity_type, 'node' AS field_data_field_toto_gallery_node_entity_type, 'node' AS field_data_field_showroom_level_node_entity_type
FROM
node node
LEFT JOIN location_instance location_instance ON node.vid = location_instance.vid
LEFT JOIN location location ON location_instance.lid = location.lid
INNER JOIN field_data_field_toto_gallery field_data_field_toto_gallery ON node.nid = field_data_field_toto_gallery.entity_id AND (field_data_field_toto_gallery.entity_type = 'node' AND field_data_field_toto_gallery.deleted = '0')
LEFT JOIN field_data_field_multiple_product_sku field_data_field_multiple_product_sku ON node.nid = field_data_field_multiple_product_sku.entity_id AND (field_data_field_multiple_product_sku.entity_type = 'node' AND field_data_field_multiple_product_sku.deleted = '0')
LEFT JOIN location_phone location_phone ON location_instance.lid = location_phone.lid
LEFT JOIN location_fax location_fax ON location_instance.lid = location_fax.lid
LEFT JOIN field_data_field_showroom_level field_data_field_showroom_level ON node.nid = field_data_field_showroom_level.entity_id AND (field_data_field_showroom_level.entity_type = 'node' AND field_data_field_showroom_level.deleted = '0')
LEFT JOIN field_data_field_showroom_type field_data_field_showroom_type ON node.nid = field_data_field_showroom_type.entity_id AND (field_data_field_showroom_type.entity_type = 'node' AND field_data_field_showroom_type.deleted = '0')
LEFT JOIN field_data_field_showroom_inventory_records field_data_field_showroom_inventory_records ON node.nid = field_data_field_showroom_inventory_records.entity_id AND (field_data_field_showroom_inventory_records.entity_type = 'node' AND field_data_field_showroom_inventory_records.deleted = '0')
LEFT JOIN field_data_field_record_type_id field_data_field_record_type_id ON node.nid = field_data_field_record_type_id.entity_id AND (field_data_field_record_type_id.entity_type = 'node' AND field_data_field_record_type_id.deleted = '0')
WHERE (( (node.status = '1')
AND (node.type IN ('showrooms'))
AND (location.latitude > '32.859795378699'
AND location.latitude < '34.306986221301'
AND location.longitude > '-85.206632058424'
AND location.longitude < '-83.469478341576')
AND ((COALESCE(ACOS(0.83308162574562*COS(RADIANS(location.latitude))*(0.098658823381208*COS(RADIANS(location.longitude)) + -0.99512131751311*SIN(RADIANS(location.longitude))) + 0.55315007443282*SIN(RADIANS(location.latitude))), 0.00000)*6371570.9191628) < '80467.35')
AND (location.province = 'GA')
AND (location.city LIKE 'Atlanta' ESCAPE '\\') )
AND( (field_data_field_toto_gallery.field_toto_gallery_value = '1')
OR (field_data_field_multiple_product_sku.field_multiple_product_sku_value NOT LIKE 'NULL' ESCAPE '\\') ))
ORDER BY field_data_field_showroom_level_field_showroom_level_value DESC,
field_data_field_showroom_type_field_showroom_type_value DESC,
location_distance ASC,
field_data_field_showroom_inventory_records_field_showroom_i DESC,
field_data_field_record_type_id_field_record_type_id_value ASC,
field_data_field_toto_gallery_field_toto_gallery_value DESC
LIMIT 10 OFFSET 0
I would recommend, that you learn about the PROCEDURE ANALYSE function of MySQL: http://dev.mysql.com/doc/refman/5.0/en/procedure-analyse.html
It will tell you which joins might not have an index they can use. From only looking at your query but without knowing the structure or data of the tables, we can't give you a good adivce. Usually you should have an index on every column, you use in a JOIN and ORDER BY part of you query and you might have some indexes for the columns used in the WHERE clause.
Here are some things to try immediately to see if you can improve performance.
Try a compound index on the location table on (province, city, latitude, longitude, lid). That compound index will, hopefully, accelerate the WHERE criteria computation for your locations.
Make sure your latitude and longitude columns have the FLOAT or DOUBLE data type.
Try a compound index on the node table on (status, type, vid). That index should help locate the exact node records in your WHERE clause and accelerate your joins.
Eliminate the spherical geometry computation from your WHERE clause. You already have the bounding box range restriction, and you're already sorting by distance, so you shouldn't get too many extra locations this way. And, if you do, they shouldn't be too far away by a factor of more than 4/pi.
Can you get rid of the SELECT DISTINCT and just use SELECT? Finding distinct values is a data-intensive operation.
For some helpful information on the distance computation and the bounding box optimization, please see this. http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/

SQLite SELECT except where single column has duplicate

How can I ensure that s.user_id and w.stage_id do not have duplicate rows? You can see in the screengrab that user_id 117 occurs in two rows. I want to prevent this - perhaps by only including the latest submission in the query?
My returned data is as follows:
My query:
SELECT DISTINCT r.breakout_id, r.case_id, r.stage_id, r.chart_id, s.stage1_choice,s.user_id,w.stage1,w.user_id
FROM Results as r, Submissions as s, Switch as w
WHERE r.breakout_id = '1' AND s.breakout_id = '1' AND w.breakout_id = '1' AND s.user_id = w.user_id AND w.case_id = r.case_id AND s.case_id = r.case_id AND s.stage1_choice IS NOT NULL ORDER BY w.user_id
Try this:
SELECT r.breakout_id, r.case_id, r.stage_id, r.chart_id,
s.stage1_choice,s.user_id,max(w.stage1),w.user_id
FROM Results as r, Submissions as s, Switch as w
WHERE r.breakout_id = '1' AND s.breakout_id = '1' AND w.breakout_id = '1' AND s.user_id = w.user_id
AND w.case_id = r.case_id AND s.case_id = r.case_id AND
s.stage1_choice IS NOT NULL
GROUP BY r.breakout_id, r.case_id, r.stage_id, r.chart_id,
s.stage1_choice,s.user_id,w.user_id
ORDER BY w.user_id;

Filtering with multiple OR / AND in MySQL

This is my first question here. I searched a lot off docs, but can't find answer.
I have 3 tables.
product_main(with idx and name)<br />
proudct_attributes (with idx 'pid gid value)<br />
product_attributes_groups (with idx name) <br />
Now I trying to filter products by attributes. I have no problem with single attribute, but I can't make it work to filter with several conditions i.e. (red or blue , but only new)
SELECT `pid` FROM `product_attributes`
LEFT JOIN `product_main` ON `product_attributes`.`pid` = `product_main`.`idx`
LEFT JOIN `product_attributes_groups` ON `product_attributes`.`gid` = `product_attributes_groups`.`idx`
WHERE
(
(`product_attributes_groups`.`name` = 'color' AND `product_attributes`.`value` ='red' )
OR
(`product_attributes_groups`.`name` = 'color' AND `product_attributes`.`value` ='blue' )
)
AND
(`product_attributes_groups`.`name` = 'condition' AND `product_attributes`.`value` ='new' )
EDIT:
This helped:
select pm.idx
from product_attributes as pa join
product_main as pm
on pa.pid = pm.idx join
product_attributes_groups as pig
on pa.gid = pig.idx
group by pm.idx
having sum(pig.name = 'color' AND pa.value in ('red' , 'blue')) > 0 and
sum(pig.name = 'condition' AND pa.value ='used') > 0;
Answer by Gordon, with a little editing.
You have a "set-within-sets" query, where you are trying to find matches within a group (attributes on a product). I like to solve these with aggregation and a having clause:
select pm.pid
from product_attributes pa join
product_main pm
on pa.`pid` = pm.`idx` join
product_attributes_groups pig
on pm.`gid` = `pig`.`idx`
group by pm.pid
having sum(pig.`name` = 'color' AND `pa`.`value` in ('red' , 'blue')) > 0 and
sum(pig.`name` = 'condition' AND pa.`value` ='new') > 0;
Each condition in the having clause is counting the number of rows for each pid that match one condition.
A condition like
WHERE
`product_attributes_groups`.`name` = "something"
AND `product_attributes_groups`.`name` = "something else"
can never be true. Check what you're aiming to do and rewrite your filter.
Try this one. It should work with the combination (name AND (red OR blue)) OR (condition AND new)
SELECT `pid` FROM `product_attributes`
LEFT JOIN `product_main` ON `product_attributes`.`pid` = `product_main`.`idx`
LEFT JOIN `product_attributes_groups` ON `product_attributes`.`gid` = `product_attributes_groups`.`idx`
WHERE
(`product_attributes_groups`.`name` = 'color' AND (`product_attributes`.`value` ='red' OR `product_attributes`.`value` ='blue') )
OR
(`product_attributes_groups`.`name` = 'condition' AND `product_attributes`.`value` ='new' )

Categories