Date between two values - Lavarel SQL - mysql

I have a structure table like this : Start_date End_date
Now with today's date, I should go and get all the data including from Start_Date and End_Date, what can I do?
I tried with
SELECT *
FROM text
WHERE Start_date BETWEEN '2021-10-10' AND '2021-10-08'
OR End_date BETWEEN '2021-10-08' AND '2021-10-10
but to no avail ...

The whereBetween method in Laravel will determine if an items value is between the given range.
$start = '2021-10-08';
$end = '2021-10-10';
Text::whereBetween('start_date', [$start, $end])
->whereBetween('end_date', [$start, $end])
->get();

if you just want to get data from start to end date you can use this eloquent Code
$start_date = "2020-10-20";
$end_date = "2021-10-20";
Text::where(function ($wh) use ($start_date, $end_date) {
$wh->whereBetween('Start_date', [$start_date, $end_date])->orwhereBetween('End_date', [$start_date, $end_date]);
})->get();
here is a raw query from the above eloquent code
select * from `users` where (`Start_date` between '2020-10-20' and '2021-10-20' or `End_date` between '2020-10-20' and '2021-10-20')
if you want to find data from start to end date including today's date you can you this eloquent Code
$start_date = "2020-10-20";
$end_date = "2021-10-20";
Text::where(function ($wh) use ($start_date, $end_date) {
$today_date = date('Y-m-d');
$wh->where(function ($or_where) use ($start_date, $end_date) {
$or_where->whereBetween('Start_date', [$start_date, $end_date])
->orwhereBetween('End_date', [$start_date, $end_date]);
})->orwhereRAW("('{$today_date}' between `Start_date` and `End_date`)");
})->get();
here is a raw query from the above eloquent code
select * from `text` where ((`Start_date` between '2020-10-20' and '2021-10-20' or `End_date` between '2020-10-20' and '2021-10-20') or ('2021-10-09' between `Start_date` and `End_date`))

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();

Create Doctrine query

I have a quiz application where played rounds are logged in UserPerformanceEntity. The corresponding MySQL table looks like:
UserPerformance
---------------
id (PK)
user
start_time
end_time
max_level
I want to display some statistics, like 'You performed better than x% of players'. To calculate the percent of players who performed worse than the current I want to execute the following MySQL query:
SELECT COUNT(DISTINCT `user`)
FROM `UserPerformance`
WHERE
(end_time IS NOT NULL
AND end_time NOT LIKE '0000-00-00 00:00:00')
AND `user` != :current_user
AND max_level < :current_level
ORDER BY max_level DESC
But I have no idea how to implement this with doctrine. How should my querybuilder look like?
try this
$query = $this->createQueryBuilder('u');
$query->select('COUNT(DISTINCT u.id) as usercount')
->where('u.end_time IS NOT NULL')
->andWhere('u.end_time NOT LIKE :end_time')
->andWhere('u.id != :current_userid')
->andWhere('u.max_level < :current_level')
->setParameter('end_time', '0000-00-00 00:00:00')
->setParameter('current_userid', $current_userid)
->setParameter('current_level', $current_level)
->setMaxResults(1);
$result = $query->getQuery()->getResult();
return $result[0]['usercount'] ;
The only change is, you need id from current user instead object
Additional information that a user can play many times, so user id is not unique, one user can have many records. This is my solution:
$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder();
$result = $qb->select('COUNT(DISTINCT p.user) AS usercount')
->from('LoginetFBappVagoBundle:UserPerformanceEntity', 'p')
->where(
$qb->expr()->andX(
$qb->expr()->isNotNull('p.endTime'),
$qb->expr()->neq('p.endTime', ':endTime')))
->andWhere($qb->expr()->neq('p.user', ':userId'))
->andWhere($qb->expr()->lt('p.maxLevel', ':maxLevel'))
->setParameter('endTime', '0000-00-00 00:00:00')
->setParameter('userId', $userid)
->setParameter('maxLevel', $level)
->getQuery()
->getResult();
I started from #Alexander Keil's answer, but I used expressions, and I figured out that there is no need to group the (end_time IS NOT NULL AND end_time NOT LIKE '0000-00-00 00:00:00') part. However if I pass '0000-00-00 00:00:00' in the expression instead setting as a parameter, I get an error. And at last I have to count the distinct users the get the correct result.

Convert this query to eloquent

I'm a noob in Laravel. can anyone help me write this query in eloquent
SELECT
*
FROM
table
WHERE
(
STR_TO_DATE(`date`, '%m/%d/%Y') BETWEEN '2014-08-05'
AND '2014-08-05'
)
ORDER BY
id
If you want to use your query as is, just use DB::raw
http://laravel.com/docs/queries#raw-expressions
DB::raw(SELECT * FROM table WHERE ( STR_TO_DATE(date, '%m/%d/%Y') BETWEEN '2014-08-05' AND '2014-08-05' ) ORDER BY id);
Well making the assumption that your model is called Table, if your field is of type DATE, you can do this:
Table::where('date', '>=', '2014-08-05')
->where('date', '=<', '2014-08-05')
->get();
Alternatively you can do:
Table::select('table.*', DB::raw("STR_TO_DATE(date, '%m/%d/%Y') as date_format"))
->where('date_format', '>=', '2014-08-05')
->where('date_format', '=<', '2014-08-05')
->get();
You may try this:
$from = '...';
$to = '...';
DB::table('table')->whereBetween('date', array($from, $to))->get();
Or using Eloquent:
ModelName::whereBetween('date', array($from, $to))->get();

MySQL - DATE_ADD month interval by each month

I have written a function below to give me the number of jobs an employee has done in a particular 30 day period (each ID in the 'jobs column' of the table represents 1 job).
the function work fine if I only want to look back 4 week. the problem however is that I want the count to start at the beginning of each month. for example, if a person views the records on the 10th December 2013 I need the records to show all the work for December (but not the records for the preceding 30 days).
Below is my function:
$interval_1month = 'interval 4 WEEK';
function statsHowMuchWorkDoneByStaff ($staff_id, $timeInterval)
{
global $dbc;
$select = " SELECT
COUNT(job_id) AS totalnumberWork ";
$from = " FROM
staffwork
";
$where = " WHERE
staff_id = $staff_id
AND
FROM_UNIXTIME(entrytime) >= now() - $timeInterval";
$query = $select.$from. $where;
$result = mysqli_query ($dbc, $query)
or trigger_error("Query: $query\n<br />MySQL Error: " . mysqli_error($dbc));
if(mysqli_num_rows($result))
{
$row = mysqli_fetch_array ($result, MYSQLI_ASSOC);
$result = safe_output($row['totalnumbernewcontacts']) ;
return $result ;
}
else
{
return false;
}
}
Any advise on how to proceed would be greatly appreciated.
UPDATE: here is my datatable:
CREATE TABLE staffwork(
staff_id MEDIUMINT UNSIGNED NOT NULL,
job_id MEDIUMINT UNSIGNED NOT NULL,
data_table VARCHAR (65) NOT NULL,
entrytime int(11) NOT NULL,
INDEX message (staff_id)
);
If I understand correctly and you want to calculate COUNT(job_id) for a specific month by supplying any date of that month as a parameter, then you can do it this way
SELECT COUNT(job_id) total
FROM staffwork
WHERE staff_id = 1
AND entrytime >= UNIX_TIMESTAMP(LAST_DAY('2013-12-10') + INTERVAL 1 DAY - INTERVAL 1 MONTH)
AND entrytime < UNIX_TIMESTAMP(LAST_DAY('2013-12-10') + INTERVAL 1 DAY)
Note: This query is index friendly because it doesn't convert entrytime to datetime but rather convert range values (which are constants for the query) to unix time. Make sure that you have indices on entrytime and staff_id to be able to take advantage of that.
Here is SQLFiddle demo
And while you're at it consider to learn and use prepared statements instead of interpolating query strings leaving your code vulnerable for sql injections.
That being said your php function might look like this
function statsWorkDoneByStaffMember($staff_id, $month) {
global $dbc;
$sql = "
SELECT COUNT(job_id) total
FROM staffwork
WHERE staff_id = ?
AND entrytime >= UNIX_TIMESTAMP(LAST_DAY(?) + INTERVAL 1 DAY - INTERVAL 1 MONTH)
AND entrytime < UNIX_TIMESTAMP(LAST_DAY(?) + INTERVAL 1 DAY)
";
$stmt = $dbc->prepare($sql);
if (!$stmt) {
trigger_error('Prepare failed: ' . $dbc->error);
}
$stmt->bind_param('iss', $staff_id, $month, $month);
if(!$stmt->execute()) {
trigger_error('Execute failed: ' . $dbc->error);
}
$stmt->bind_result($result);
$stmt->fetch();
$stmt->close();
return $result;
}
Sample usage:
$dbc = new mysqli('localhost', 'user', 'password', 'dbname');
$staff_id = 1;
//Get the number of job_id for the current month
$total = statsWorkDoneByStaffMember($staff_id, date('Y-m-d'));
//Get the number of job_id for a specific month
$total = statsWorkDoneByStaffMember($staff_id, '2013-07-01');

Codeigniter And MYSQL DateTime

I Have a query as follows:
$query = $this->db->get_where('Bookings', array('Status' => 0, 'Driver_ID' => null, 'Date'=> 'NOW()'));
The Date field is a datetime type, and I want to be garbing records where their date is the same as today, however the above, and everything else I have tired does not work.
Can anyone one show me how to correctly pull records that date it today, ignoring the time part of datetime.
Thanks for any help
UPDATE
I Have now converted the query to the following
$start = date('Y-m-d 00:00:00');
$end = date('Y-m-d 23:59:59');
$query = $this->db->get_where('Bookings', array('Status' => 0, 'Driver_ID' => null, 'Date' => 'BETWEEN '.$start.' AND '.$end));
However still no luck, just retuning no results!
I would try
$this->db->where('Status', 0);
$this->db->where('Driver_ID', null);
$this->db->where('DATE(Date)', date('Y-m-d'), FALSE);
$query = $this->db->get('Bookings');
$params = array('Status' => 0, 'Booking_Date'=> date('Y-m-d'));
$this->db->query('SELECT * FROM Bookings WHERE Status=? AND Driver_ID Is Null AND Date(Booking_Date) = ?',$params);
Think that will work
In your code, you are saying you want a DateTime field to be NOW(). The problem is that NOW() gives a DateTime value, that is, a date in the form "YYYY-MM-DD" followed by a time in the form "HH:MM:SS".
What your query is doing is saying "Give me records where the Date is today, at this exact second". What you want is "Give me records where the Date is today".
This is why using DateTime fields in a database is usually cumbersome. You will have to convert your Date field to be just the date, without the time, using the MySQL function DATE(), and instead of NOW() which returns a DateTime value, you will want to use CURDATE() which returns only the Date value. I am not experienced with CodeIgniter specifically, but try:
$query = $this->db->get_where('Bookings', array('Status' => 0, 'Driver_ID' => null, 'DATE(Date)'=> 'CURDATE()'));
(I don't know if you can apply MySQL functions to fields with $this->db->get_where).
MySql standard datetime format is date("Y-m-d H:i:s").
So you query will need to get everything for the current day, so a where clause someything like;
SELECT * FROM `Bookings` WHERE `Date` BETWEEN date("Y-m-d 00:00:00") AND date("Y-m-d 23:59:59")