Using PHP to select rows between dates through variables - php

I'm trying to fetch all rows where the date column's value is a day in july using the code below:
$july="07";
$query=$conn->prepare("SELECT * FROM table WHERE date BETWEEN '2018-?-01' AND '2018-?-31'");
$query->execute($july,$july);
$row=$query->setFetchMode();
I have also tried like this:
$july="07";
$month_1="'2018-".$july."-01'";
$month_2="'2018-".$july."-31'";
$query=$conn->prepare("SELECT * FROM table WHERE date BETWEEN ? AND ?");
$query->execute(array($month_1,$month_2));
$row=$query->setFetchMode();
1st case, I get the following error:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens' in file.php on line 35
I assume I get that error because I cannot have '?' in a query between single brackets.
Second case, I get nothing at all.
Solved it with this:
SELECT * FROM table WHERE YEAR(date)=2018 AND MONTH(date)=?

Query 1 fails because you can't quote a placeholder.
Query 2 fails because the single quotes get escaped by the driver and then the whole escaped string gets wrapped in quotes. Roughly
date BETWEEN '\'2018-07-01\''
There are a few ways you could accomplish this.
Take the first 7 values of your date column and compare that against your string.
$date = '2018-07';
...then execute the query like ...
WHERE substr(date, 1, 7) = ?
You also could use the concat method which keeps the placeholder from being quoted.
$july="07";
$query=$conn->prepare("SELECT * FROM table WHERE date BETWEEN concat('2018-', ?, '-01') AND concat('2018-', ?, '-31')");
$query->execute(array($july, $july));
$row=$query->setFetchMode();

First case error is because you passed two variables to PDO::execute() and its expecting array there.
Suggested Reading...
http://php.net/manual/en/pdostatement.execute.php
Second case .. ummm.. you sure it does nothing?
Select * from mytable where date <= '2018-07-31' and date >= '2018-07-01'
or whatever... this maybe ...
select * from mytable where date between UNIX_TIMESTAMP(STR_TO_DATE('Jul 01 2018 12:00AM', '%M %d %Y %h:%i%p')) and UNIX_TIMESTAMP(STR_TO_DATE('Jul 31 2018 11:59PM', '%M %d %Y %h:%i%p'))
Never use * to return all columns in a table–it’s lazy. You should only extract the data you need. Even if you require every field, your tables will inevitably change. -https://www.sitepoint.com/mysql-mistakes-php-developers/

Related

Bind the name of a parameter

In Doctrine, is it possible to bind the name of a parameter
(contrary to binding the value of a parameter)?
Why I need it
There is a table having 7 boolean columns, one for each day of the week: monday, tuesday, etc. (these correspond to the structure of the calendar entity defined by GTFS, https://gtfs.org/schedule/reference/#calendartxt).
Given a day of the week (say, monday), I want to get all rows, which are available on Mondays, i.e.:
$statement = $this
->getEntityManager()
->getConnection()
->prepare('
SELECT id
FROM calendar
WHERE monday = 1
');
Generally, I want to be able to supply the name of a day in that query, which I can do simply by:
->prepare("
SELECT id
FROM calendar
WHERE $dayName = 1
");
I wonder whether it's possible to use the parameter binding for the names of parameters, i.e. something like
$statement = $this
->getEntityManager()
->getConnection()
->prepare('
SELECT id
FROM calendar
WHERE :dayName = 1
');
$statement->bindValue('dayName', $dayName);
which does not work, see below.
What I tried
#1
WHERE :dayName = 1
which translates to the following SQL query:
SELECT calendar.id
FROM calendar
WHERE 'monday' = 1
and, because that condition is never true, returns an empty set, [].
#2
WHERE `:dayName` = 1
SELECT calendar.id
FROM calendar
WHERE `'monday'` = 1
Column not found: 1054 Unknown column ''monday'' in 'where clause'
#3
WHERE ":dayName" = 1
# no query
Invalid parameter number: number of bound variables does not match number of tokens
This is of course not possible.
Within the statement, placeholders can be used as parameter markers to indicate where data values are to be bound to the query later when you execute it. The parameter markers should not be enclosed within quotes, even if you intend to bind them to string values. Parameter markers can be used only where expressions should appear, not for SQL keywords, identifiers, and so forth.
In short: you can use parameter markers for literals (string, numbers, ..) only
If you can't change your database design I would recommend using another SQL statement with a simple bit check:
prepare("select id, (monday +
tuesday * 2 +
wednesday * 4 +
thursday * 8 +
friday * 16 +
saturday * 32 + sunday *64) as day
from calendar having (day) & (1 << :daynumber)")
Now you can simply check if a service is available on a specific weekday, by binding the daynumber (monday=0, tuesday=1, .. sunday=6).

How to fetch blog posts by month using MONTH() in mySQLi

I have my datetime going into the DB like this:
$CurrentTime = time();
$DateTime = strftime("%b-%d-%Y %H: %M: %S", $CurrentTime);
In phpMyAdmin it looks like this:
May-15-2018 01: 04: 00
Feb-08-2018 13: 49: 23
etc...
The field is varchar(50)
I'm trying to extract posts from this table based on the month that the post was created.
I have tried the following:
"SELECT * FROM admin_panel WHERE MONTH(datetime) ='2'"
"SELECT * FROM admin_panel WHERE MONTH(STR_TO_DATE(datetime, '%b-%d-%Y %H: %M: %S')) ='2'"
I don't get an error, but nothing is returning. Any ideas on how I can correct this?
You can use MYSQL STR_TO_DATE with MONTH
"SELECT * FROM admin_panel WHERE MONTH(STR_TO_DATE(`datetime`,'%b-%e-%Y %H:%i:%s')) = 5"
Adding Year with AND condition
SELECT * FROM admin_panel WHERE MONTH(STR_TO_DATE(`datetime`,'%b-%e-%Y %H:%i:%s')) = 5 AND YEAR(STR_TO_DATE(`datetime`,'%b-%e-%Y %H:%i:%s')) = 2018
The following works when the 'datetime' column is defined as DATETIME, yyyy-mm-dd h:i:s (2018-06-14 14:29:15) and not as VARCHAR,
SELECT * FROM admin_panel where extract(month from datetime)='02'
I think, if you use a VARCHAR instead of a DATE.. type, then you will have to typecast string to a date for performing any date-based functions on it in a query. Imo, it is better to have date stored in DATE.. format and let MySQL store it in some format; but you could format it using DATE_FORMAT functions for displaying.
When column type is DATETIME, month() call also can be used as in,
SELECT * FROM admin_panel WHERE month(datetime)='02'

Comparing date() in sql query

I have 5 records in mysql database and these records have recorded date within this date interval.
$year=2015;
$month=8;
$datefrom=1;
$dateto=31;
$startdate='$year-$month-$datefrom 00:00:00';
$enddate='$year-$month-$dateto 23:59:59';
So I write a query to get these records out like this:
$sql = "SELECT id FROM newpost WHERE email=:email AND :startdate <= poststart <= :enddate AND postapproved=1";
Given that poststart column in table newpost has SQL Datetime format like this: "Y-m-d H:i:s".
But when I changed variable $year = 2016, I still got 5 results? It should return no record. Because those 5 records are recorded between 1 - 31 August 2015.
So I thought I did something wrong in the sql query especially the comparing date part but I could not configure out how to fix it?
Please help!
You can use BETWEEN in your query
$sql = "SELECT id FROM newpost WHERE email=:email AND (poststart BETWEEN :startmonth AND :endmonth) postapproved=1"
Use single quotes to wrap your date values
$sql = "SELECT id FROM newpost WHERE email=:email AND poststart BETWEEN ':startdate' AND ':enddate' AND postapproved=1";
A couple quick things to check to make sure it's not a syntactical error:
Your variable names don't match up. You defined startdate and enddate, but then in the query you used startmonth and endmonth.
You should probably also use leading zeros in your month and day, i.e.:
$month='08';
$datefrom='01';

MySQL Query Interpret Date String as Date

I saw a couple of posts on this problem, but I'm not getting it to work correctly. I have a PHP variable that I initially POST as a string. To be able to handle a one week date range, I am converting this using strToTime into datetime format (e.g. July 22, 2013 echos as 1374476400).
My table has its dates stored as text in a Y-m-d format (e.g. July 22, 2013 is stored as 2013-07-22). I need to run a query comparing these two values to find dates that fall within my one week range, so I am trying to convert that text into datetime format for comparison purposes.
Here is the SQL that I am using:
$wk_begin = $_POST['wk_begin'];
$wk_begin = strToTime($wk_begin);
$wk_end = $wk_begin + 8;
$sql = "SELECT * FROM myTable WHERE (DATE(date)>=$wk_begin AND DATE(date)<$wk_end)";
I'm not getting any errors, but my query isn't picking any records up, even though i know that there are 7 matching records in the table. So I have two questions:
1) Is there a better way to go about this?
2) If I am on the right track, how can I get the sql statement to convert the text based dates into a big integer so that I can do the comparison correctly.
Any help is appreciated. Thanks!
EDIT: Thanks for all of the suggestions. I've changed the table so that the dates are stored in 'date' format (no more strings). Here is the updated code. Still not picking up any values:
$wk_begin = $_POST['wk_date'];
$wk_end = $wk_begin + 7;
$sql = "SELECT * FROM Workouts WHERE 'date' BETWEEN '$wk_begin' AND '$wk_end'";
date is a reserved word in mysql, to use it as a field name surround it in backticks.
Also your variable insertions need to be surround in apostrophes
SELECT * FROM myTable WHERE (DATE(`date`)>='$wk_begin' AND DATE(`date`)<'$wk_end'
A better solution (in addition to making the date field a date field) would be to use the db library's escaping and quoting mechanisms when building the sql statement.
Also since you are storing your dates in Y-m-d format the cast to date is unneccessary since string comparison on dates formated this way evaluate the same as the string. So
$sql = "SELECT * from myTable WHERE `date` >= ".$db->quoteAndEscape($wk_begin)." and `date` < ".$db->quoteAndEscape($wk_end);
UPDATE
Based on this date can be used as an unquoted field name.
<?php
$wkbegin = $_POST['wk_begin'];
$wk_begin = strToTime($wkbegin);
$d=date('j', $wk_begin)+8;
$m=date('n', $wk_begin);
$y=date('Y', $wk_begin);
$wk_end = date('Y-m-d', mktime(0,0,0, $m, $d, $y));
$wkbegin = date('Y-m-d', $wk_begin);
$sql = "SELECT * FROM `myTable` WHERE `date`>='".$wkbegin."' AND `date`<'".$wk_end."'";
?>

Getting mySQL date_format to display in PHP

This could sound like a very simple question to many of you, but I seem to be having trouble getting a basic date_format to work with my mySQL statement and then to be displayed using php. Here is the code that I currently have:
$result = mysql_query("SELECT *, DATE_FORMAT('timestamp', '%W %D %M %Y') as date FROM articleDB WHERE userID='".$_SESSION["**"]."' ORDER BY timestamp DESC LIMIT 8");
Then trying to display it using:
echo ' Posted: '.$row['timestamp'].'';
All I want is to format the date from a PHP myAdmin timestamp to the format I want.
Cheers
Use backticks ( `` ) or nothing at all instead of single-quotes ('`) around your field in your query:
$result = mysql_query("SELECT *, DATE_FORMAT(`timestamp`, '%W %D %M %Y') as date FROM articleDB WHERE userID='".$_SESSION["**"]."' ORDER BY timestamp DESC LIMIT 8");
Backticks ( `` ) creates a reference to a table member, single-quotes creates a string ('). You were basically trying toDATE_FORMATthe string'timestamp'` instead of the field.
Also, since you are using as to create a field alias, you want to refer to that field using the alias when outputting:
echo ' Posted: '.$row['date'];
you need to display the "date" column that you calculate/format in the select statement, the timestamp column contains the unformatted original date value.
echo ' Posted: '.$row['date'];
since in your SQL query you define the date formatting as date you access it by $row['date'].

Categories