I have a sql booking question. The table has idstylist, bdate, stime and etime.
Basically the stylist can only do one job at a time. So when placing a booking I need to check that that stylist is not already busy on another booking. Here is my clash method;
public function checkClash($bdate, $stime,$stylist){
$query = sprintf("SELECT id FROM table WHERE (date=%s AND idstylist=%s) AND (%s BETWEEN stime AND etime)",
$this->db->GetSQLValueString($bdate, "date"),
$this->db->GetSQLValueString($stylist, "int"),
$this->db->GetSQLValueString($stime, "text"));
$result = $this->db->query($query);
if($result && $this->db->num_rows($result) > 0){
return true;
}
return false;
}
As far as I understand my query is selecting all bookings from (date) where idstylist is this and the start time is >= $stime but <=$stime.
So for example I have a row in the database that looks like this;
id | date | idstylist | stime | etime
1 | 2014-12-05 | 68 | 07:00:00 | 07:30:00
Now Im trying to place a booking for the same stylist at 07:10:00 on the same date which should fail but the system is allowing me to make this booking. I cant see whats wrong with my query.
//next check for clashes in the booking table
$clash = $bookings->checkClash($_POST['bdate'],$_POST['stime'], $_POST['stylist']);
if($clash==true){
$errors[] = "Booking clashes. Please try again";
}
This is turning into a debugging session.
From your SQL: (stime>=%s AND etime<=%s)
Replace with values: ('7:00' >= '7:10' AND '7:30' <= '7:10')
I gues you want: (%s BETWEEN stime and etime)
Related
I have a Model Charter that hasMany BlackoutRanges. I am trying to setup a scope to return charters that do not have a blackoutRange created for 3 dates. In our system a blackoutRange is a single day.
Pseudocode would look something like this:
// query where doesnt have blackoutDates on all three of the following dates:
// start date === date passed in
// start date === date passed in plus 1 days
// start date === date passed in plus 2 days
I tried to do some logical grouping and came up with this and I also logged my raw sql query to see what it looks like:
$dayTwo = $date->copy()->addDays(1);
$dayThree = $date->copy()->addDays(2);
return $query->whereDoesntHave("blackoutRanges", function(Builder $subQuery) use($date, $dayTwo, $dayThree){
$temp = $subQuery->where(function($queryOne) use($date) {
return $queryOne->whereDate('start', $date)->where('trip_id', NULL);
})->where(function($queryTwo) use($dayTwo) {
return $queryTwo->whereDate('start', $dayTwo)->where('trip_id', NULL);
})->where(function($queryThree) use($dayThree) {
return $queryThree->whereDate('start', $dayThree)->where('trip_id', NULL);
});
logger($temp->toSql());
return $temp;
});
select * from `blackout_ranges` where `charters`.`id` = `blackout_ranges`.`charter_id` and (date(`start`) = ? and `trip_id` is null) and (date(`start`) = ? and `trip_id` is null) and (date(`start`) = ? and `trip_id` is null)
I've also logged the dates passed in and they are:
[2022-06-07 19:00:58] local.DEBUG: 2022-06-09 00:00:00
[2022-06-07 19:00:58] local.DEBUG: 2022-06-10 00:00:00
[2022-06-07 19:00:58] local.DEBUG: 2022-06-11 00:00:00
An example of the start column of a BlackoutRange would be: 2022-07-21 04:00:00
Would the fact that they are not matching timestamps be a reason for this scope not working?
And how do I know it's not working? I added blackoutRanges for a specific charter for the entire month of June and it's still being returned.
I am looking for any advice on this one as I've been plugging away now for a day and a half and have gotten no where.
Is there a way to write a MySQL query to get records by monthly for example:
Starting from the current month:
----- Jan -----
Record 1
Record 2
----- Feb -----
Record 1
Record 2
----- March-----
Record 1
Record 2
I have starting and ending timestamp and start_date, end_date(MM/DD/YYYY format) column in my db table.
solved by getting start date & end date of month
$month_start_time = strtotime(date('Y-m-01', $timestamp)." 00:00:00");
$month_end_time = strtotime(date('Y-m-t', $timestamp)." 23:59:59");
$sdate = date('d', $month_start_time);
$edate = date('d', $month_end_time);
$j=0;
for($k=$sdate; $k <= $edate; $k++){
$start_date = $k.date('/m/Y', $month_start_time);
$stimestamp = strtotime(date('Y/m', $month_start_time).'/'.$k." 00:00:00");
$end_date = strtotime(date('Y/m', $month_start_time).'/'.$k." 23:59:59");
//then pass in mysql query
}
i have 2 table, table items and table borrowing.
structure items table :
| id | items_name | stock (amount)|
structure borrowing table :
| id | items_id | date | amount |
when someone want to borrow the items, column stock will decrease (minus) as much as loan amount.
so my code is be like :
$items_id = $_POST['items_id'];
$datenow = date('Y-m-d');
$amount = $_POST['amount'];
$input = mysql_query("INSERT INTO borrowing VALUES('$items_id', '$datenow', '$amount')") or die(mysql_error());
$item = mysql_query("SELECT stock FROM items WHERE id='$items_id'");
$row = mysql_fetch_assoc($item);
$stockleft = $row['stock'] - $amount;
$update = mysql_query("UPDATE items SET siswa_nis='$stockleft'") or die(mysql_error());
i am worried if using that, will error on middle run.
what i want is if last query or second query error, first query will rollback, something like that.
so how the trigger and how i call trigger on php ?
thank you in advance.
I have a table of events, each of which has a start date and an end date.
I need to display a list of days and show which events are occurring on each day.
E.g. Say I have on event that runs mon-wed and another that runs tues-thurs I'm trying to create a table like so:
Mon: Event 1
Tue: Event 1, Event 2
Wed: Event 1, Event 2
Thu: Event 2
The only way I can see to do this is either by running a query for each day or by loading all events for given date range and then duplicating them in my code if they last for more than one day. Both approaches seem hacky and I'm sure I'm missing something.
Is there a neater way to do this?
Structure:
id INT
name VARCHAR
start_date DATE
end_date DATE
Current query (slightly simplified because this database structure is appalling):
SELECT *
FROM events
WHERE start_date <= $somedate
AND end_date >= $somedate
...where $somedate is a given date. (Yes, I am escaping it properly in my code!)
Select your events for a particular date range (I assume a particular month). Then loop over the days in that month and have another, inner loop that displays any events that occur on that date.
<?php
$events = getEvents(); // some function that returns events from database
echo '<ol class="calendar">';
for ($i = 1; $i <= cal_days_in_month(); $i++) {
echo '<li>';
$beginning = mktime(0, 0, 0, date('n'), $i, date('Y'));
$end = mktime(23, 59, 59, date('n'), $i, date('Y'));
$events_on_day = array();
foreach ($events as $event) {
if ($event->start_date <= $end && $event->end_date >= $beginning) {
$events_on_day[] = $event;
}
}
if ($events_on_day > 0) {
echo '<ul>';
foreach ($events_on_day as $event_on_day) {
echo '<li>' . $event_on_day->name . '</li>';
}
echo '</ul>';
}
}
echo '</ol>';
?>
There's probably a better way, but off the top of my head I would say to create a table of possible dates, then simply
select * from events
inner join possibleDates on possibleDates.Date >= start_date and possibleDates.Date <= end_date
First you'll propably have to get all dates between start_date and end_date of each event.
Put the in a temp. table like:
|Weekday| Event_name|
|Mo | Event1 |
|Tu | Event1 |
|We | Event1 |
|We | Event2 |
|Th | Event2 |
|Fr | Event2 |
and then group_concat the events by group by on weekday.
This link will help you to get the dates between start and end date of each event.:
Get a list of dates between two dates
You can do it in one query if you must, though I would advise getting a weekday-table like Jan Zeiseweis also suggests. Working SQLfiddle: http://www.sqlfiddle.com/#!2/e618d9/1/0
SELECT wk.day, GROUP_CONCAT(e.name, '') events
FROM (
SELECT 'Monday' day, 0 dayIndex
UNION
SELECT 'Tuesday' day, 1 dayIndex
UNION
SELECT 'Wednesday' day, 2 dayIndex
UNION
SELECT 'Thursday' day, 3 dayIndex
UNION
SELECT 'Friday' day, 4 dayIndex
UNION
SELECT 'Saturday' day, 5 dayIndex
UNION
SELECT 'Sunday' day, 6 dayIndex
) wk
LEFT JOIN Events e
ON WEEKDAY(e.start) <= wk.dayIndex
AND WEEKDAY(e.end) >= wk.dayIndex
GROUP BY wk.day ORDER BY wk.dayIndex
I'm getting a weird return when executing this query :
SELECT * FROM rrp
WHERE end > "2012-12-31"
nothing is returned, although I have one row on this table which "end" column is greater than "2012-12-31":
rrp
id_r | id__b | start | end | quantity
27 29 2012-01-01 2012-05-05 1
31 29 2012-11-01 2013-01-01 1
EDIT : startand endare date fields
EDIT : I used wrong database for my tests => wrong result
the issue was coming from Zend_Date when adding a day to a date:
$start = "2012-12-31";
$nStart = new Zend_Date($start, "YYYY-MM-dd");
$end = new Zend_Date($nStart);
$end->addDay(1);
When i echoed $end : echo $end->get("YYYY-MM-dd");
it outputs 2013-12-31
Most likely an issue with how the dates are formatted
This should help
http://dev.mysql.com/doc/refman/5.0/en/using-date.html
If end is a DATE column, it should work as expected:
SELECT
STR_TO_DATE('2013-01-01', '%Y-%m-%d') < "2012-12-31",
STR_TO_DATE('2012-05-05', '%Y-%m-%d') < "2012-12-31"
... returns 0, 1 in my box.
The only possible flaw I can think of is that your system's default date format is not %Y-%m-%d:
SELECT ##DATE_FORMAT
In that case, you need to specify a format every time:
SELECT *
FROM rrp
WHERE end > STR_TO_DATE('2012-12-31', '%Y-%m-%d')