SQL Doctrine year's eve - mysql

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

Related

Quoting of Queries in perls mojolicious

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;

optimize sql query inside foreach

I need help optimizing the below querys for a recurrent calendar i've built.
if user fail to accomplish all task where date
This is the query i use inside a forech which fetched all dates that the current activity is active.
This is my current setup, which works, but is very slow.
Other string explained:
$today=date("Y-m-d");
$parts = explode($sepparator, $datespan);
$dayForDate2 = date("l", mktime(0, 0, 0, $parts[1], $parts[2], $parts[0]));
$week2 = strtotime($datespan);
$week2 = date("W", $week2);
if($week2&1) { $weektype2 = "3"; } # Odd week 1, 3, 5 ...
else { $weektype2 = "2"; } # Even week 2, 4, 6 ...
Query1:
$query1 = "SELECT date_from, date_to, bok_id, kommentar
FROM bokningar
WHERE bokningar.typ='2'
and date_from<'".$today."'";
function that makes the foreach move ahead one day at the time...
function date_range($first, $last, $step = '+1 day', $output_format = 'Y-m-d' )
{
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$dates[] = date($output_format, $current);
$current = strtotime($step, $current);
}
return $dates;
}
foreach:
foreach (date_range($row['date_from'], $row['date_to'], "+1 day", "Y-m-d")
as $datespan)
if ($datespan < $today)
Query 2:
$query2 = "
SELECT bok_id, kommentar
FROM bokningar b
WHERE b.typ='2'
AND b.bok_id='".$row['bok_id']."'
AND b.weektype = '1'
AND b.".$dayForDate2." = '1'
AND NOT EXISTS
(SELECT t.tilldelad, t.bok_id
FROM tilldelade t
WHERE t.tilldelad = '".$datespan."'
AND t.bok_id='".$row['bok_id']."')
OR b.typ='2'
AND b.bok_id='".$row['bok_id']."'
AND b.weektype = '".$weektype2."'
AND b.".$dayForDate2." = '1'
AND NOT EXISTS
(SELECT t.tilldelad, t.bok_id
FROM tilldelade t
WHERE t.tilldelad = '".$datespan."'
AND t.bok_id='".$row['bok_id']."')";
b.weektype is either 1,2 or 3 (every week, every even week, every uneven week)
bokningar needs INDEX(typ, date_from)
Instead of computing $today, you can do
and date_from < CURDATE()
Are you running $query2 for each date? How many days is that? You may be able to build a table of dates, then JOIN it to bokningar to do all the SELECTs in a single SELECT.
When doing x AND y OR x AND z, first add parenthes to make it clear which comes first AND or OR: (x AND y) OR (x AND z). Then use a simple rule in Boolean arithmetic to transform it into a more efficient expression: x AND (y OR z) (where the parens are necessary).
The usual pattern for EXISTS is EXISTS ( SELECT 1 FROM ... ); there is no need to list columns.
If I am reading it correctly, the only difference is in testing b.weektype. So the WHERE can be simply
WHERE b.weektype IN ('".$weektype2."', '1')
AND ...
There is no need for OR, since it is effectively in IN().
tilldelade needs INDEX(tilldelad, bok_id), in either order. This should make the EXISTS(...) run faster.
Finally, bokningar needs INDEX(typ, bok_id, weektype) in any order.
That is a lot to change and test. See if you can get those things done. If it still does not run fast enough, start a new Question with the new code. Please include SHOW CREATE TABLE for both tables.

Selecting past events up to current hour

I have a table that contains events data. I also have a list of dates that I need to check through. So I loop though the given dates and query my table. I need to select the events that we on a given date and if the date is the same as today, I only need events that took place before certain time. The time is stored in a military format, like 14:30.
I think I've overcomplicated my query logic:
$current_date = date('Y-m-d');
$current_time = date('H:i');
The reason I use PHP time and date, because I can have an accurate time from a server I control. MySQL time is off by a few hours...
SELECT *
FROM events
WHERE org.id = ".$ID."
AND (
(
DATE(events.date) = '".$givenDate."'
AND
'".$givenDate."' < '".$current_date."'
)
OR
(
DATE(events.date) = '".$givenDate."'
AND
'".$givenDate."' < '".$current_date."'
AND
events.time < '".$current_time."'
)
)
SELECT *
FROM events
WHERE org.id = ".$ID."
AND date(events.date) = '".$givenDate."'
and if ('".$givenDate."' = '".$current_date."',
events.time < '".$current_time."', true)

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;