Quoting of Queries in perls mojolicious - mysql

I have a mojolicious app where I am using lots of queries, which are hard coded, so I am trying to differentiate between code and query by having new .sql files for each query.
I have some problems with the following query:
my $sql = $self->db->query(qq(
select
a,
b,
c
from
table
where
date_format(d, "%m") >= $month
and
date_format(d, "%m") <= $month
and
date_format(d, "%Y") >= $year
and
date_format(d, "%Y") <= $year
and
if(? = "", a, a=?)
), $a, $a);
The query above work perfect, but when I try to read it from a file my result is null.
my $path = Mojo::File->new('/path/to/file')->slurp;
my $sql = $self->db->query($path, $month,$month, $year, $year, $a, $a);
It doesn't matter if I use double quotes, single quotes or each perl function of quoting, the result is always null. When I get my params with $sth->{ParamValues} I get the right params for each call.
After coupule of hours of debugging and testing, I found out that the problem lies on the sql function "date_format" which is not called properly, but I couldn't find out why not. An alternative could be to format the time inside perl, but is not a beautiful way to handle that. I also tried to use sql variables for setting the params.
My sql file looks like:
select
a,
b,
c
from
table
where
date_format(d, "%m") >= ?
and
date_format(d, "%m") <= ?
and
date_format(d, "%Y") >= ?
and
date_format(d, "%Y") <= ?
and
if(? = "", a, a=?)

The solution was to use the interval function of mysql which is smart enough to calculate the date.
For the parameters I used the sprintf function and used one variable instead of 2.
my $date = sprintf('%4d-%02d-01');
select sum(a), sum(b) from t1 where c between $date and $date + interval 1 month;

Related

How to write the below eloquent query code using raw query in laravel?

My eloquent query:
$data = (new Model())->whereDate('start_date', '<=', Carbon::today())
->whereDate('end_date', '>=', Carbon::today())
->count();
The raw query I have tried:
$data = (new Model())->select(DB::raw("COUNT(id) as countData where date(start_date) <= NOW() and date(end_date) >= NOW()"))->get();
How can I write my eloquent query as raw query. The below raw query gives me syntax violation error;
This is because of how you are constructing your query. If you inspect the generated SQL statement you'll see that the SQL FROM clause is actually on the end of your statement and not at all where it should be.
You'll want to split your WHERE clauses out and use either where or whereRaw. For example:
$data = (new Model)->select(DB::raw('COUNT(id) as countData'))
->whereRaw('date("start_date") <= NOW() AND date("end_date") >= NOW()')
->get();
Your question was a little unclear but if you want to do what you did with eloquent in raw query, be noted that the select function of DB in raw by itself, so simply write your query inside select function:
$tableName = (new Model)->getTable();
$data = DB::select("
SELECT COUNT(`id`) as `countData` FROM `$tableName`
WHERE DATE(`start_date`) <= NOW() AND DATE(`end_date`) >= NOW()
")->first();
Alternatively you may use whereRaw function of your Model:
$data = Model::whereRaw(
"DATE(`start_date`) <= NOW() AND DATE(end_date) >= NOW()"
)->count();

SQL(mysql) comparing times not working

I am trying to select the message from a row where the start and end time is the same as $a and $b. But it does not bring any results however when i remove the end time it brings all the results.
I dont understand why its not working.
$a = '16:50:00';
$b = '17:00:00';
echo $times;
$query1 = ("SELECT message FROM db WHERE DATE(starttime) >= '$a' AND DATE(endtime) <= '$b'");
As you say the starttime and endtime columns are of type TIME. Running a DATE() on them will really mess the time up.
SELECT DATE('17:00:00);
will return 2017-00-00 i.e the best date it can make out of a time. Which of course is no use to you at all.
So mod your query to
SELECT message FROM db WHERE starttime >= '$a' AND endtime <= '$b'

SQL Doctrine year's eve

that's is strange, maybe is my fault. Today I launch my test and 2 of they faults (yesterday dont). This test use a control date of some bookings, and I presume the problem is that today is 31/12. I'll show you the code:
$em = $this->getEntityManager();
$query = $em->createQuery(
'SELECT b
FROM AppBundle:Booking b
WHERE b.bookingDate >= CURRENT_DATE()
AND b.bookingDate <= CURRENT_DATE()+1
ORDER ASC b.bookingDate'
)
return $booking = $query->getResult();
That way is the only way i found to check that the booking have a date at today. Is possible that this fault becouse today is 31/12? Do you have some solution?
sorry for bad english, thanks.
You can calculate the dates by Php:
$today = new DateTime('now');
$tomorrow = new DateTime('tomorrow');
$em = $this->getEntityManager();
$query = $em->createQuery(
'SELECT b
FROM AppBundle:Booking b
WHERE b.bookingDate >= :today
AND b.bookingDate < :tomorrow
ORDER BY b.bookingDate ASC'
);
return $query->setParameters(array(
'today' => $now->format('Y-m-d'),
'tomorrow' => $tomorrow->format('Y-m-d')
))->getResult();
You can avoid var $booking and return result directly.
Also you have missed ; at the end of createQuery and ORDER is ORDER BY.
Also beware with namespaces, maybe you must to use new \DateTime('now');
CURRENT_DATE()+1
returns
20161232
which seems to be pretty wrong.
A way to make it works as you want it to would be this:
DATE_ADD(CURRENT_DATE(), INTERVAL 1 DAY);
which returns
2017-01-01

Convert MySQL fetch array query to redbean PHP

I have 2 buttons which execute a post operations and set a hidden variable which is used to set the MySQL query to filter the database according to date
if result = today
$query = "SELECT id,customer_name,CAST( `register_date` AS DATE ) AS dateonly,status,
DATE_FORMAT(book_date, '%m/%d/%y') FROM table WHERE book_date
BETWEEN (CURDATE() - INTERVAL 1 DAY) AND CURDATE()";
if result = week
$query = "SELECT id,customer_name,CAST( `register_date` AS DATE ) AS dateonly,status,
DATE_FORMAT(book_date, '%m/%d/%y') FROM table
WHERE book_date BETWEEN (CURDATE() - INTERVAL 7 DAY) AND CURDATE()";
I then want to use something like
$result=mysql_query($query);
while ($mytable=mysql_fetch_array($result))
{
loop and display all the information in array in a table
}
But I need the red bean equivalent of this.
The easiest way is to just paste the $query inside the sql function:
$results=R::getAll($query);
foreach($results as $row){
echo $row['id'];
}
The next way is to manually build the query.... which may just make it look sloppier in my opinion:
$results=R::$f->begin()->select('id, customer_name, CAST( register_date AS DATE ) AS dateonly,status, DATE_FORMAT(book_date, '%m/%d/%y')')->from('table')->where('book_date BETWEEN (CURDATE() - INTERVAL 1 DAY) AND CURDATE())->get();
The final way is to grab results via redbean and handle them manually:
$results=R::find('table','book_date BETWEEN (CURDATE() - INTERVAL 7 DAY) AND CURDATE()');
Then loop through the results, configuring data along the way in php.
I always use this when I have to access a lot of data from mysql:
while ($row = mysqli_fetch_array($query)) { #converts query into array
$array[] = $row;
}
$array will be a multidimensional array. $array[x][column_name] will get you your data, x being the row which you want to access it from. Hope this helped.

php mysql group by date with yyyy-mm-dd format

I had a mysql table called events with the fields: id, date, and name.
The date field has the format yyyy-mm-dd hh::mm:ss edit: meaning it is in datetime format
I want to group the events by day, and I wasn't sure how to approach this- is there a way to select only the month and day from the field? or should i use PHP after I select all the "events"
my end goal is to have something like this:
March 10th:
event1,
event2
March 11th:
event4,
event5
I found MySQL select using datetime, group by date only but I'm not sure how to implement it:
SELECT DATE_FORMAT(date, '%H%i'), DATE_FORMAT(date, '%M %D'), name FROM events ORDER BY date
Thanks!
EDIT:
ended up using this:
$sql = "select team1, team2, DATE_FORMAT(date,'%Y-%m-%d') as created_day FROM games WHERE attack = '1' GROUP BY created_day";
$result = mysql_query($sql);
$curDate = "";
while (list($team1, $team2, $date) = mysql_fetch_row($result))
{
if ($date != $curDate)
{
echo "$date --------\n";
$curDate = $date;
}
echo "game data: $team1 $team2";
}
If you use group by you will not get one row out of it. So the way you want is not possible through Group By AFAIK.
$query = "SELECT distinct(DATE_FORMAT(date, '%M %D')) as d FROM yourtable";
$result = mysql_query($query);
while($row = mysql_fetch_assoc($result)) {
echo $row['d']
$sql = "SELECT * FROM yourtable WHERE DATE_FORMAT(date, '%M %D')='$row[d]'";
$rs = mysql_query($query);
while($r = mysql_fetch_assoc($rs)) {
echo "event";
}
}
You should indeed use php to get this done. But since most of current system sepate logic from display, I'd use only one pass and not (NUMBER OF DAYS + 1) SELECTs, and prepare an array that I can reuse later for my display.
$query = "SELECT DATE_FORMAT(date, '%M %D') as d, name FROM yourtable ORDER BY date";
$foo=array();
$result = mysql_query($query);
while($row = mysql_fetch_assoc($result)) {
//some logic to test if it's safe to add the name
$foo[$row['d']][]=$row['name'];
}
And then when i'd need it (through a template or your "view")
foreach($foo as $date => $events) {
echo $date . ":\n\t";
echo implode(",\n\t", $events);
echo "\n";
}
so it fits the format you set to yourself.
Hope that helped
I think from that question/answer, you can get something like this instead
March 10th, event1
March 10th, event2
March 11th, event4
March 11th, event5
It does not really 'group' dates as your wish but I think you can use php to continue from this result.
I agree with Kharaone, separate logic from display. That being said, I think that something similar to this query might be what you are looking for:
SELECT A FROM
(
SELECT DATE_FORMAT(date,'%M %D:') AS A, DATE(date) AS B, 1 AS C FROM games GROUP BY DATE(date)
UNION ALL
SELECT name AS A, DATE(date) AS B, 2 AS C FROM games
) X
ORDER BY B, C ASC;