Date comparison between MSSQL varchar and PHP string does not work - why?

782 views Asked by At

So I got a database running on a Microsoft SQL Server 11, with the table hpfc_prices containing multiple entries in a chronologic sequence, which roughly looks like this:

|date (varchar(255))|time (varchar(255))|price (decimal(25,10))|
|===================|===================|======================|
|01.01.2016         |00:00              |[some value]          |
|01.01.2016         |01:00              |[some value]          |
|01.01.2016         |02:00              |[some value]          |
|...                |...                |...                   |
|01.01.2016         |23:00              |[some value]          |
|02.01.2016         |00:00              |[some value]          |
|02.01.2016         |01:00              |[some value]          |
|...                |...                |...                   |

This table is spanning from January 1st 2016 to December 31st 2020, each entry representing one hour. Now I want to load parts of the table, let's say the whole year 2017, in a PHP script. For that I have to use Medoo as database framework, and I'm running following code:

$db = new medoo($database_config);
$hpfcStart = "01.01.2017";
$hpfcEnd = "31.12.2017";
$arr = $db->select("hpfc_prices",["date","time","price"],["AND" => ["date[>=]" => $hpfcStart, "date[<=]" => $hpfcEnd]]);
var_dump($arr);

The Medoo query is by debug translated to this SQL query:

SELECT "date","time","price" FROM "hpfc_prices" WHERE "date" >= '01.01.2017' AND "date" <= '31.01.2018

The problem now is that the output now contains all of the table, and not just specifically all entries for 2017. I assume the query fails at the date comparison, since Medoo compares a string with a varchar. In my experience this worked with MySQL, but I'm not so sure about MSSQL/Medoo. Can anyone tell me how I can compare the dates correctly?

3

There are 3 answers

4
MonkeyZeus On BEST ANSWER

If you are willing to use Medoo's query() function alongside quote() then try this:

WHERE convert(date, 104) >= convert('01.01.2017', 104)

For the record, this is going to kill performance. Not sure of MSSQL's index capabilities but I would add an index with this definition if possible

convert(date, 104)
0
Dan Bracuk On

php has these functions which allow you to convert strings to dateTime objects.

The sql server cast function works on your strings:

select cast ('02.01.2016' as date)

returns 2016-02-01

Use the php function to create datetime variables and pass them to sql server as parameters. Then your query resembles this:

where cast([date] as date) >= @firstParameterFromPHP
and cast([date] as date) < @secondParameterFromPHP
3
Sami Kuhmonen On

Since you are comparing strings, 02.01.2016 is bigger than 01.01.2017. You should never store dates as strings, or if you really have to, at least use a format that can be compared. That is, items go from larger to smaller. Then 2016.01.02 will be smaller than 2017.01.01.

But you will still have to use the proper formatting etc. Much easier to just use proper datatypes.

If the existing format is set, you can use CONVERT with style 104 to convert both sides to DATETIME and compare them.