SELECT ... INTO Understanding its behavior - mysql

I was told that I could check whether a SELECT statement finds a column with the syntax
$rows = query( "SELECT * FROM tbl WHERE id = idx");
if ( $rows == false )
and it seems to work.
Anyway, if I check if ( $rows == 0 ) it doesn't return the same value.
Shouldn't 0 and false be the same (apart from the type, of course)?
What's the actual value returned by the query when it finds no row? I ask because it doesn't seems to be false, since the statement var_dump( $rows === false ) prints false..
***EDIT: I'm sorry guys, query() was a function from a library someone else wrote and I had no idea (i'm starting now with sql...). It simply excutes an SQL statement, returning an array of all rows in result set or false on (non-fatal) error (like row not found).
I have still a little question, though.
The function returns false when it finds no row, so shouldn't I be able to catch that with if ( $rows === false )?
Why var_dump(false) doens't print me out anything, while var_dump(true) prints me out 1?

I'm not pretty sure if you use simple mysql_* functions, MySQLi or PDO but in any case $rows is not returning the number of resulting rows. It is a boolean value / object returned / created depending of success of your query.
$sql = $mysqli->query("SELECT * FROM tbl WHERE id='1'");
if(!$sql->error)
$number_of_rows = $sql->num_rows; // for sure it will output 1

Related

MySQL Select : where time is greater then and less than time

I have a function that accepts two time parameters: $start_time, $end_time
each parameter is define as time in php as
$start_time = date("H:i:s",strtotime($start)); ->like "06:12:44"
$end_time = date("H:i:s",strtotime($end)); ->like "08:22:14"
I want to build a query that gives the results between these times
This is my function
function statistics_connected_hour($gateway_id , $date_sql ,$start_time ,$end_time){
$statistics_connected = mysql_query(
"SELECT *
FROM cdr_table
WHERE OwnerUserID ='$_SESSION[user_id]'
AND GatewayID = $gateway_id
AND DATE(Dialed) = $date_sql
AND Dialed != 0
AND Hour(StartTime) BETWEEN ('$start_time') AND ('$end_time')
");
return $statistics_connected;
}
StartTime Column in the DB define as "2012-12-28 13:32:28"
The query does not return any results although there are supposed to return
When I check ->
$num = mysql_num_rows($statistics_connected);
It always returns 0 in $num
Can anyone help me understand what the problem is?
You want TIME(), not HOUR().
SELECT * FROM cdr_table
WHERE OwnerUserID = '$_SESSION[user_id]'
AND GatewayID = $gateway_id
AND DATE(Dialed) = $date_sql
AND Dialed != 0
AND TIME(StartTime) BETWEEN '$start_time' AND '$end_time'
Also, I'd strongly suggest escaping all variables you're embedding in SQL code with mysql_real_escape_string() or equivalent, even if you're sure there's nothing harmful in them, just to make it a habit.
Note that a query like this may be intrinsically inefficient, since it cannot make use of indexes on the StartTime column. If there are a lot of potentially matching rows in the table, it could be a good idea to denormalize your table by creating a separate column storing only the time part of the StartTime and setting up an index on it (possibly combined with other relevant columns).
The reason is because you are extracting the HOUR and comparing with the time, you need to cast the time part
Try your query as::
SELECT
*
FROM cdr_table
WHERE
OwnerUserID ='$_SESSION[user_id]'
AND GatewayID = $gateway_id
AND DATE(Dialed) = $date_sql
AND Dialed != 0
AND DATE_FORMAT(StartTime,'%r') BETWEEN ('$start_time') AND ('$end_time')

Null value matching in mySql

I have three tables in a mysql database . Deseasetype(DTID,TypeName) , Symptom(SID, SymptomName, DTID) , Result(RID, SID1, SID2, SID3, result).1st two table, i think is clear enough.
In result table: there will be combination's of symtoms and any values of SymID1/ SymID2/ SymID3 can be null. here i send a picture of the table result.
I want to input some symptom and output will be the result from the 'Result' table.
For that i wrote this query:
$query = "select Result from result where (result .SID1= '$symptom1') AND (result.SID2= '$symptom2' ) AND (result.SID3 = '$symptom3')";
This work only when three symptom's have value. but if any of the symptom's are null, then no result found. May be the query should be more perfect.
**please avoid any syntax error in my writing.
That's because you are comparing NULL to an empty string, and they aren't equal. You could try this instead:
SELECT Result
FROM symptom
WHERE IFNULL(symptom.SID1, '') = '$symptom1'
AND IFNULL(symptom.SID2, '') = '$symptom2'
AND IFNULL(symptom.SID3, '') = '$symptom3'
Notes:
You need to correctly escape the values of $symptom1, $symptom2 and $symptom3.
This won't efficiently use indexes.
As mark pointed out, the query is eventually falling down to compare with null if you are not escaping the null.
Or you can slightly change your logic to show a empty symptom with value '0' and then using the coalesce function you can easily build your query.
Does this work?
$query = "select Result from result
where (result.SID1 = '$symptom1' OR result.SID1 IS NULL) AND
(result.SID2 = '$symptom2' OR result.SID2 IS NULL) AND
(result.SID3 = '$symptom3' OR result.SID3 IS NULL)";

Using comparison as alias in select for Doctrine2

Trying to do this in Doctrine2:
...->createQuery('SELECT m.id, (m.status != 1) as verified...
But that throws an error - if I take parenthesis off I get another error. How do I achieve this m.status comparison?
Thanks
Doctrine 2 doesn't support these comparisons in the SELECT clause (at least not up to 2.3, not sure about 2.4).
You can use a CASE expression as workaround:
SELECT m.id, CASE WHEN m.status != 1 THEN 1 ELSE 0 END AS verified ...
or:
SELECT m.id, CASE WHEN m.status = 1 THEN 0 ELSE 1 END AS verified ...
If you need verified for an ORDER BY clause (or something like that), but don't actually need it in the result, you can use the HIDDEN expression:
SELECT m.id, CASE WHEN m.status = 1 THEN 0 ELSE 1 END AS HIDDEN verified ...
A completely different solution is to write a custom DQL function.
You can use the solution proposed here: Cumulative DQL with Doctrine
When working with entities, keep in mind that adding selects will make the query return an array for each result:
$res = $em->createQueryBuilder()
->from('BlogPost', 'p')
->select('p')
->addSelect('(2+3) AS dummy')
->getQuery()->getResult();
Iterating over $res will return an array:
foreach($res as $mixed){
echo get_class($mixed[0]); //$mixed[0] contains the BlogPost
echo $mixed['dummy']; //displays the dummy result (5)
}
check this out: 13.2.4. Using Expr* classes to create conditionals
using Expression methods you could do something like:
$qb = $this->entityManager->createQueryBuilder();
$query = $qb->select('m.id')
->from('Entities\MyEntity', 'm')
/*neq() is the "not equal" comparison function*/
->where($qb->expr()->neq('m.status', $someValue)),
->getQuery();

mySQL: get hash value for each row?

Currently I'm manually creating a string where I concatenate all the values in each row in my table. I'm hashing this string for each row to get a hash value for the current values (/status) of the row, which I'm later is using to determine if the row has changed.
Instead of doing this manually, is there an build-in way i mySQL to get a unique hash value for each row?
you could do something like
SELECT MD5(concat(field1, field2, field3, ...)) AS rowhash
but you can't get away from listing which fields you want, as concat(*) is not an option (syntax error).
It's better to use concat_ws(). e.g. two adjacent column: 12,3 => 1,23 .
Sorry, this still has some problems. Think about the null value, empty string, string can contain ',', etc...
A program is required to generate the hash statement, which should replace null to specific value (for null-able columns), and also use the seldom used char/byte as separator.
There are problems with CONCAT, e.g. CONCAT('ab', 'c') vs CONCAT('a', 'bc'). Two different rows, but result is the same. You could use CONCAT_WS(';', 'ab', 'c') to get ab;c but in case of CONCAT_WS(';', ';', '') vs CONCAT_WS(';', '', ';') you still get the same result.
Also CONCAT(NULL, 'c') returns NULL.
I think the best way is to use QUOTE:
SELECT MD5(CONCAT(QUOTE(c1), QUOTE(c2), QUOTE(c3))) AS row_hash FROM t1;
Result of: select (concat(quote('a'), quote('bc'), quote('NULL'), quote(NULL), quote('\''), quote('')));
is: 'a''bc''NULL'NULL'\''''
Also, don't use GROUP_CONCAT() to get hash of table, it has limit: https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_group_concat_max_len
Instead, CHECKSUM TABLE might be better, but you can't skip columns with CHECKSUM TABLE https://dev.mysql.com/doc/refman/5.7/en/checksum-table.html
Well I made a little script that could do excactly what you want, and maybe what others want... so here it goes...for PHP that is...
first you have to make a list of columns of the table, then you make a "case when" statement for each column based on their type and put that in the concat_ws statement and then you hash it with sha1...i've used this method on very large tables (600000+ records) and the speed is quite good when selecting all records. also I think that it is faster to concat the required data in a concat_ws and explode it in php or whatever you are using, but that is just a hunch...
<?
$query= mysql_query("SHOW COLUMNS FROM $table", $linklive);
while ($col = mysql_fetch_assoc($query)) {
$columns[] = mysql_real_escape_string($col['Field']);
if ($col['Key'] == 'PRI') {
$key = mysql_real_escape_string($col['Field']);
}
$columnsinfo[$col['Field']] = $col;
}
$dates = array("date","datetime","time");
$int = array("int","decimal");
$implcols = array();
foreach($columns as $col){
if(in_array($columnsinfo[$col]['Type'], $dates)){
$implcols[] = "(CASE WHEN (UNIX_TIMESTAMP(`$col`)=0 || `$col` IS NULL) THEN '[$col EMPTY]' ELSE `$col` END)";
}else{
list($type, $rest) = explode("(",$columnsinfo[$col]['Type']);
if(in_array($columnsinfo[$col]['Type'], $dates)){
$implcols[] = "(CASE WHEN ( `$col`=0 || `$col` IS NULL ) THEN '[$col EMPTY]' ELSE `$col` END)";
}else{
$implcols[] = "(CASE WHEN ( `$col`='' || `$col` IS NULL ) THEN '[$col EMPTY]' ELSE `$col` END)";
}
}
}
$keyslive = array();
//echo "SELECT $key SHA1(CONCAT_WS('',".implode(",", $columns).")) as compare FROM $table"; exit;
$q = "SELECT $key as `key`, SHA1(CONCAT_WS('',".implode(", ",$implcols).")) as compare FROM $table";
?>

LINQ to SQL generates negative conditions in WHERE clause

I am using LINQ to SQL to retrieve data, using boolean conditions (BIT columns in SQL). My LINQ query looks something like this:
var query = from r in db.Requests
select r;
query = query.Where(r => r.Completed == someBooleanVal);
query = query.Where(r => r.Cancelled == someOtherBool);
return query.ToList();
The 'Where()' gets applied in a different method, that's why I'm putting it in separately.
When the boolean values are given as false, the generated SQL looks something like this:
SELECT [t0].[col1], [t0].[col2], [t0].[col3], [t0].[etc]
FROM [dbo].[Requests] AS [t0]
WHERE (NOT(([t0].[Cancelled]) = 1) AND (NOT(([t0].[Completed]) = 1)
in stead of what I would use:
WHERE [t0].[Cancelled] = 0 AND [t0].[Completed] = 0
This runs very, very slowly. I strongly suspect that it is because of the negative conditions on the boolean values it generated (all the selected columns are covered by an index, and the two columns in the where clause have a separate index on them).
Why is it generating negative conditions? How can I fix it?
var query =
from r in db.Requests.Where(r => r.Completed == someBooleanVal && r.Cancelled == someOtherBool)
select r;
return query.ToList();
Hope it can help you and have a nice day.