I have an eloquent model where i got two columns 'startdate' and 'enddate'. I wanna display all the models that are ongoing in the current week, i.e. any date between 'startdate' and 'enddate' that matches any date of the current week.
I first tried to get by only using the startdate like this:
$startOfWeek = Carbon::now()->startOfWeek()->startOfDay();
$endOfWeek = Carbon::now()->endOfWeek()->endOfDay();
$modelThisWeek = Model::whereBetween('startdate', [$startOfWeek, $endOfWeek])->get();
But naturally, anything that started more than a week ago, but is still ongoing ('enddate' is not finished yet) won't show up.
How could i get all the models valid for the current week efficiently?
Edit: So what I kinda want to do (sounds stupid now) is to get all the dates in between 'startdate' and 'enddate' like in an array for example, get a second array of all dates in between the current week and use like an array_intersect and get those models. I hope I explained that a bit more clearly this time.
Edit 2: Some sample data and expected result.
Data in DB:
--------------------------------------------------
| ID | some_other_col | startdate | enddate |
--------------------------------------------------
| 1 | ... | 12. Jan 17 | 20. Feb 17 |
--------------------------------------------------
| 2 | ... | 12. Jan 17 | 18. Jan 17 |
--------------------------------------------------
| 3 | ... | 30. Jan 17 | 04. Feb 17 |
--------------------------------------------------
| 4 | ... | 04. Feb 17 | 07. Feb 17 |
--------------------------------------------------
| 5 | ... | 08. Feb 17 | 10. Feb 17 |
--------------------------------------------------
So if I want all the models within the current week:
29. Jan 17 - 05. Feb 17
I expect the models with the ID 1, 3, 4;
Like all the models that are ongoing within the two dates (startOfWeek and endOfWeek).
Your problem is quite simple if you define 2 possible outputs
Your model got starting and ending dates
Your model got only starting date (ending date is null)
First output you already covered, so only second output need to cover up
Your query should look like for both outputs
$modelThisWeek = Model::where(['startdate','>='$startOfWeek],
['enddate','<=', $endOfWeek])
->orWhere(function ($query) {
$query->where('enddate', '>', $endOfWeek);
})
})->get();
It will maybe need some tweaks (I didn't totally understand you if you check for this week and you want in output still ongoing model which may started few weeks ago etc). Try it and if there is any more additional condition feel free to ask.
Related
Is it possible to execute a different select query for each day of the week. I currently have the following columns: id, station_name, week_type and service.
The week_type is an enom value with the following options: 'Mon-Thur', 'Fri', 'Sat', 'Sun', 'Special'.
The service column only has a varchar value of the time of day. It needs to apply as the service operates the same on a weekly schedule depending on the week_type.
+-----------------------------------+------------+-----------+-----------+
| id |station_name| week_type | service |
+-----------------------------------+------------+-----------+-----------+
| 1 | Station1 | Mon-Thur | 08:15:00 |
| | | | |
| 2 | Station2 | Sat | 10:15:00 |
+-----------------------------------+------------+-----------+-----------+
As seen in the table above, when it is Saturday in my timezone and is equal to the week_type, then it should only show Saturday rows. And etc. for the other columns.
Any help would be much appreciated, as I am new to SQL.
I think you really need to work out on the table. Why don't you normalize your table.
station_services
id|station_name
station_working_days
id|station_id|weekday_id|working_hours
If you dont want week days as seperate table then you can hardcode from 1 as sunday to saturday as 7
station_working_days
id|station_id|weekday|working_hours
By normalising you will get all the flexibility in future too.
In case if the stations all the time have the same working hours then use the following table normalisation so that it may help you.
station_services
id|station_name|working_hours
station_working_days
id|station_id|weekday_id
I am trying to select data, when inserting the data it has an auto insert of the date when submitting. So when data is inserted it inserts the current date.
However, in my table I have week beginnings, so I am trying to select the data inside of that week:
mysql> select * from week;
+---------+------+------------+
| week_id | week | date |
+---------+------+------------+
| 1 | 1 | 2014-12-29 |
| 2 | 2 | 2015-01-05 |
| 3 | 3 | 2015-01-12 |
| 4 | 4 | 2015-01-19 |
| 5 | 5 | 2015-01-26 |
| 6 | 6 | 2015-02-02 |
| 7 | 7 | 2015-02-09 |
| 8 | 8 | 2015-02-16 |
| 9 | 9 | 2015-02-23 |
| 10 | 10 | 2015-03-02 |
| 11 | 11 | 2015-03-09 |
| 12 | 12 | 2015-03-16 |
| 13 | 13 | 2015-03-23 |
| 14 | 14 | 2015-03-30 |
| 15 | 15 | 2015-04-06 |
| 16 | 16 | 2015-04-13 |
| 17 | 17 | 2015-04-20 |
e.g.
select * from table where date='2015-04-06';
However the data will not be selected and presented because the inserted date was 2015-04-10. The only way to retrieve that data is by doing this:
select * from table where date='2015-04-10'; < when the data was inserted
So my question is, is it possible to select that data from that week beginning?
So if I select data from 2015-04-06 it should show data from the range of 2015-04-06 to 2015-04-12, is that possible?
Hopefully I have explained correctly, been a bit tricky to explain let alone try to implement. I can add any more info if needed.
NOTE: I am trying to use this inside of PHP so where the date is I would just use a variable, just thought I would say.
As the week will always end 6 days from the beginning you can use the between operator and the date_add function like this:
(for your specific example):
select *
from table
where date between '2015-04-06' and date_add('2015-04-06', interval 6 day)
And using a php variable:
select *
from table
where date between '$name_of_dt_var' and date_add('$name_of_dt_var', interval 6 day)
You could also compare the week of the date the data was entered with the weeks in the week table using WEEK() function.
Assuming that week is the same value as week(), the:
select t.*
from table t
where week = week('2015-04-10');
Even if the numbers do not match, then presumably you have some base date (such as 2015-01-01 and simple arithmetic would accomplish something very similar).
I have found that the most robust way to do this sort of week processing is to truncate each date in the table (in your example 2015-04-10) to the preceding Monday at midnight. That way you can compute the week of each item by assigning it to the first day of that week.
This little formula returns the preceding Monday given any DATE or DATETIME value.
FROM_DAYS(TO_DAYS(datestamp) -MOD(TO_DAYS(datestamp) -2, 7))
For example,
set #datestamp := '2015-04-10'
SELECT FROM_DAYS(TO_DAYS(#datestamp) -MOD(TO_DAYS(#datestamp) -2, 7))
yields the value 2015-04-06.
So, if you have a table called sale you can add up sales by week like this:
SELECT SUM(amount) weekly_amount,
FROM_DAYS(TO_DAYS(datestamp) -MOD(TO_DAYS(datestamp) -2, 7)) week_beginning
FROM sale
GROUP BY FROM_DAYS(TO_DAYS(datestamp) -MOD(TO_DAYS(datestamp) -2, 7))
This is a very convenient way to handle things, because it's robust over end-of-year transitions. The WEEK() function doesn't work quite as well.
If your business rules say that your weeks begin on Sunday rather than Monday, use -1 rather than -2, as follows.
FROM_DAYS(TO_DAYS(datestamp) -MOD(TO_DAYS(datestamp) -1, 7))
I'm using a plugin for calendar bookings and reservations. I can create more calendars, but I can't set different services, prices and payment methods in one calendar.
I need two different services for the same event, so I should create two calendars, but in this case there isn't a synchronization of booking days between the calendars: I need one calendar only.
So my intention is to synchronize both the calendars via PHP and MySQL. This plugin create a specific table called "days" in the calendar db for date, like this:
| Calendar Id | Day | Month | Year |
| 01 | 01 monday available | 01 | 2014 |
| 01 | 02 tuesday available | 01 | 2014 |
| 01 | 03 wednesday booked | 01 | 2014 |
| 02 | 01 monday in pending | 01 | 2014 |
| 02 | 02 tuesday booked | 01 | 2014 |
| 02 | 03 wednesday available | 01 | 2014 |
How can I synchronize data (day, month, year) of calendar id 01 and calendar id 02?
I've found this:
How can i synchronize two database tables with PHP?
But I need to syncronize data (records) and not tables or databases.
I hope that my questione is clair, sorry for my English and thanks in advance!
You should create a new column to store if is available.
| Calendar Id | Day | Month | Year | Available
Then, you can use a trigger:
CREATE TRIGGER synchronize_update BEFORE UPDATE ON table
FOR EACH ROW BEGIN
UPDATE table SET Available = NEW.Available WHERE calendar_id <> NEW.calendar_id AND Day = New.Day And Month = NEW.Month AND Year = NEW.Year;
END;
I have found myself in need of replacing certain returned results from a MySQL Select Query. I have the following table and data (simplified for example purposes)
uid | duration | range | unique | stamp
-----------------------------------------------------------------
23 | d | 43 | 1 | 1
24 | d | 65 | 0 | 2
25 | d | 76 | 0 | 3
26 | d | 33 | 0 | 4
27 | d | 44 | 1 | 5
28 | d | 43 | 1 | 6
29 | d | 67 | 0 | 7
30 | d | 88 | 0 | 8
31 | d | 63 | 0 | 9
The stamp column is what I want to do the replace on. Rather than a simple text replace, I was wondering if its possible to run some sort of user defined function on the column and replace it dynamically.
For example If the data returned in the stamp column is a 1, I would like it to replace it with today's timestamp, if it is a 2 then yesterdays timestamp, a 3, the day before yesterdays and so on and so forth.
So my question is, is it possible to point REPLACE to a function that processes the value and then returns what to replace it with. Or if not, is there another way to accomplish this.
I could obviously post process the returned data in PHP and make the changes, but with millions of records returned, it will increase the load time considerably.
EDIT TO MAKE THINGS A BIT CLEARER: I want to replace the stamp column in the data returned from a SELECT Query, I am not storing the data anywhere, or replacing the data in the table. The table will remain unchanged.
Thanks
Absolutely possible:
UPDATE stamps
SET stamp = CURRENT_DATE - INTERVAL stamp - 1 DAY;
Fiddle here. Note that you have to decrement the stamp value by 1 to "minus 0 days" for a stamp of 1. If you remove the - 1, you'll end up storing yesterday's date for stamp values of 1.
UPDATE to answer your question about doing it on SELECT:
SELECT CURRENT_DATE - INTERVAL stamp - 1 DAY
FROM stamps;
Updated Fiddle here
You can use the case statement of mysql
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE
If you are just trying to retrieve the results, use the following:
SELECT CURDATE() - INTERVAL stamp -1 DAY FROM myTable
I'm attempting to aggregate payment histories under a single due date and create an html table similarly displayed below.
+--------------+---------------+----------------+
| Date Due | Amount Paid | Date Paid |
+--------------+---------------+----------------+
| Nov, 1 2012 | $10 | Oct, 21 2012 |
| | $15 | Oct, 18 2012 |
| Oct, 14 2012 | $20 | Oct, 13 2012 |
| | $20 | Sep, 3 2012 |
+--------------+---------------+----------------+
The problem I am facing is this:
The date due, amount paid, and date paid data fields are all in the same table row. The date due does not necessarily correspond to when the actual payment was made (maybe a payment was made 3 weeks late). Or... maybe two payments were received within the time frame of a single payment date due.
How can I efficiently tackle a problem like this and display it in a table? I've tried a few ways already and the code is too system process intensive.
EDIT: The rows in the table of the database currently look something like this:
+--------------+---------------+----------------+
| Date Due | Amount Paid | Date Paid |
+--------------+---------------+----------------+
| Nov, 29 2012 | $10 | Oct, 21 2012 |
| Nov, 15 2012 | $15 | Oct, 18 2012 |
| Nov, 1 2012 | $20 | Oct, 13 2012 |
| Oct, 14 2012 | $20 | Sep, 3 2012 |
+--------------+---------------+----------------+
But the customer has to pay $50 for every due date. In this case, the customer split up their payments and it did not apply to the current due date because of the way the data is formatted in the table.
Unfortunately, I can not change anything in the database.
The query will be
select * from table_name order by Date_Due ASC,Date_Paid ASC , Amount_Paid ASC
This query first do order by of Date_Due by ascending and after that by Date_Paid and Amount_Paid.
Assuming your query is on a single flat table, it sounds like you simply want each due date to display only once (instead of with every row).
If thats correct, I think you should just approach the problem in your php code that constructs your table rather than trying achieve this in your mysql result.