How to Trigger total number of days in mySQL - php

"I need to create a field that will show the number of days between a date and the present.
TABLE: reg_add
+------------+---------+
| Name | Type |
+------------+---------+
| hm_date | date |
+------------+---------+
| total_days | date |
+------------+---------+
My client will type in the following date for example in "hm_date": May 1, 2012.
I need "total_days" to show the total days between May 1, 2012 at the current date.
I want to achieve this on server-side, which is somewhat new to me.
I need to create a TRIGGER to always have "total_days" updated
I started with this and I'm having trouble making a trigger and getting it correct:
SELECT DATEDIFF(curdate(),hm_date) as total_days FROM reg_add
Any help would be appreciated.
Erik

You can calculate it on the fly very easy, using TIMESTAMPDIFF function -
SELECT TIMESTAMPDIFF(DAY, hm_date, NOW()) FROM reg_add;

I took a look into the MySQL Trigger Docs and from the looks of it, you can only create trigger for event types Insert, Update, and Delete. So your Trigger won't actually update your total_days field (which should be int) as you want it. [It sounds like you want it to update your field on a time basis (aka every x hours update)].
Here is the docs: http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html
I would suggest writing a cron job in php that runs once (or multiple times) per day that will update the field for you.
In your cron you should just have to run one sql statement: (This should go through the whole table and update the total_days field for each row)
UPDATE reg_add SET total_days = DATEDIFF(curdate(),hm_date)

Erik, I am using tsql, and not as familiar with mySQL, but in tsql the DATEDIFF function requires 3 parameters. The sytax is
DATEDIFF(date part, date1, date2).
I would try DATEDIFF(d,GETDATE(),hm_date) AS total_days FROM reg_add

Instead of triggers, you could use a View:
CREATE VIEW reg_add_with_total_days_VIEW
AS
SELECT hm_date
, DATEDIFF( CURDATE(), hm_date ) AS total_days
FROM reg_add ;
Then you can use the view, every time you need the total days - which will be calculated on the fly:
SELECT hm_date, total_days
FROM reg_add_with_total_days_VIEW
You can see it working in SQL-Fiddle

Related

Grouping shifts in MySQL table by week starting with sunday using PHP & MySQL

I'm writing a script using PHP & MySQL where I can record the shifts I work (HGV driver).
Upon posting the form data PHP calculates shift duration, wages accumulated, overtime, distance driven, etc, and stores it in the MySQL database.
I want to then display all shifts in a table but group them by my pay week which unfortunately starts on a Sunday.
If the pay week was Mon-Sun I wouldn't have this problem as I could use week numbers but I can't due to the week starting on a Sunday.
My code is as follows:
^^^^^^^^^^^^^^^^^^^
// DB Connection //
// Return the earliest shift in the database //
$result = $db->query("SELECT * FROM `shifts` ORDER BY `shift_start` ASC LIMIT 1");
$data = $result->fetch_assoc();
// Establish the previous Sunday //
$week_from = strtotime(date('Y-m-d',mktime(0,0,0,date('m',$data['shift_start']),date('d',$data['shift_start']),date('y',$data['shift_start']))) . 'last sunday');
// PHP Loop Goes Here //
Firstly, is the above code the most efficient way of getting the start date (previous Sunday)?
Secondly, what's the best way to loop through the weeks where there are shifts?
TIA
This is a two part question, so I will try to cover them separately.
Regarding your first question, I would suggest using the MIN() function when selecting the smallest or earliest value in a database, and ensuring you have an index on the "shift_start" column. More information on the difference between MIN() and ORDER BY/LIMIT can be found here.
Then your query would look a something like this:
SELECT MIN(`shift_start`) FROM `shifts`;
Personally, I also find MIN() far more readable.
Now, for the other (and far more complicated) question:
You've not provided much detail on what your database (or the contents) looks like. Since you're using the PHP date function, I am assuming you're saving the timestamps as UNIX instead of MySQL TIMESTAMP/DATETIME types.
Firstly, I would suggest you migrate to using a TIMESTAMP/DATETIME column type. It'll simplify the query you're attempting to run.
If you're unable to change to a TIMESTAMP/DATETIME column, then you can convert a UNIX timestamp to a DATETIME.
MySQL has a YEARWEEK() function that you can use to group by:
SELECT STR_TO_DATE(CONCAT(YEARWEEK(`shift_start`), ' Monday'), '%X%V %W') AS `date`, SUM(`wage`) AS `wage` FROM `shifts` GROUP BY YEARWEEK(`shift_start`);
This will output something similar to:
+------------+------+
| Date | Wage |
+------------+------+
| 2021-11-29 | 50 |
| 2021-12-06 | 15 |
+------------+------+

auto-delete a record when the expiry date passes [duplicate]

I would like to know how can I auto delete a record when date is expired, I'm creating a Air-ticket booking website. I need to delete from my mysql database all the expired flight details. I read somewhere that I can use cron but I have no idea how to do it. Any Help for the script will be very helpful.
You may try to use MySQL Events for that:
CREATE EVENT IF NOT EXISTS `dbName`.`eventName`
ON SCHEDULE
EVERY 1 DAY -- or 1 HOUR
COMMENT 'Description'
DO
BEGIN
DELETE FROM `dbName`.`TableName` WHERE `DateCol` < NOW();
END
NOTE that MySQL Event Scheduler need to be enabled on your server:
SET GLOBAL event_scheduler = ON;
More info here.
Deleting records is not a good idea, I will suggest you Add ActiveFrom and ActiveTo DateTime Column in your Details table then do not display the expired records in your front end.
You need the service to check expired records and delete periodically. You should use this SQL:
DELETE YourTable WHERE RecordDate < #Expiration
Cron is most suited in your situation.
Create your php file that deletes or flag the unwanted flight, the script will simply connect to the database, execute your query, and maybe output a short success/failure message.
Setup the cron job that executes that php script every X hours or whatever you want.
If you are using CPanel, you can setup your cron job from it
Make use of CRON Jobs. Have a look at the below representation.
Minutes [0-59]
| Hours [0-23]
| | Days [1-31]
| | | Months [1-12]
| | | | Days of the Week [Numeric, 0-6]
| | | | |
* * * * * home/path/to/command/the_command.sh
If you want to schedule a task to run every Saturday at 8:30am , it would most probably look like this.
30 8 * * 6 home/path/to/command/the_command.sh
Just play around with your settings and you will eventually get it.
If your table currently only has 2 fields, you'll need to add a timestamp field (with default as CURRENT_TIMESTAMP) to be able to tell when the row was added.
Then you can run the following MySQL query...
DELETE FROM `table` WHERE `timestamp` > DATE_SUB(NOW(), INTERVAL 10 MINUTE)
;
You will need to run this as a cron though.
As far as I know, it can't be done in MySQL alone.

Mysql alternate week days

My table has the following columns
| customer_id | service_start_date |
I want to provide the service on alternate week days from the service start date (eg:- every other mondays, every other tuesdays etc..)
If the service_start_date is a monday, then the service will be delivered on every other mondays.
Is there any way to query the mysql table to get all customer_ids who needs service on a particular date?
Try something like
SELECT customer_id
FROM Table as t
WHERE MOD(DATEDIFF(DATE(NOW()), DATE(service_start_date)), 14) = 0
This is assuming that your service_start_date is always a weekday.
Addition to Clami219s answer:
To get the customer(s) that need service on a particular date (as of your request), use
SELECT customer_id
FROM table_name
WHERE
service_start_date <= NOW() AND
WEEKDAY(service_start_date) = WEEKDAY('2014-06-25'); //whatever date you like to fetch

Auto delete a record in table when date is expired?

I would like to know how can I auto delete a record when date is expired, I'm creating a Air-ticket booking website. I need to delete from my mysql database all the expired flight details. I read somewhere that I can use cron but I have no idea how to do it. Any Help for the script will be very helpful.
You may try to use MySQL Events for that:
CREATE EVENT IF NOT EXISTS `dbName`.`eventName`
ON SCHEDULE
EVERY 1 DAY -- or 1 HOUR
COMMENT 'Description'
DO
BEGIN
DELETE FROM `dbName`.`TableName` WHERE `DateCol` < NOW();
END
NOTE that MySQL Event Scheduler need to be enabled on your server:
SET GLOBAL event_scheduler = ON;
More info here.
Deleting records is not a good idea, I will suggest you Add ActiveFrom and ActiveTo DateTime Column in your Details table then do not display the expired records in your front end.
You need the service to check expired records and delete periodically. You should use this SQL:
DELETE YourTable WHERE RecordDate < #Expiration
Cron is most suited in your situation.
Create your php file that deletes or flag the unwanted flight, the script will simply connect to the database, execute your query, and maybe output a short success/failure message.
Setup the cron job that executes that php script every X hours or whatever you want.
If you are using CPanel, you can setup your cron job from it
Make use of CRON Jobs. Have a look at the below representation.
Minutes [0-59]
| Hours [0-23]
| | Days [1-31]
| | | Months [1-12]
| | | | Days of the Week [Numeric, 0-6]
| | | | |
* * * * * home/path/to/command/the_command.sh
If you want to schedule a task to run every Saturday at 8:30am , it would most probably look like this.
30 8 * * 6 home/path/to/command/the_command.sh
Just play around with your settings and you will eventually get it.
If your table currently only has 2 fields, you'll need to add a timestamp field (with default as CURRENT_TIMESTAMP) to be able to tell when the row was added.
Then you can run the following MySQL query...
DELETE FROM `table` WHERE `timestamp` > DATE_SUB(NOW(), INTERVAL 10 MINUTE)
;
You will need to run this as a cron though.
As far as I know, it can't be done in MySQL alone.

Getting all entries whose birthday is today in PostgreSQL

I have the following query and I need to implement a Mailer that needs to be send out to all clients who's Birthday is today. This happens on a daily manner. Now what I need to achieve is only to select the Birthday clients using a Postgres SQL query instead of filtering them in PHP.
The date format stored in the database is YYYY-MM-DD eg. 1984-03-13
What I have is the following query
SELECT cd.firstname,
cd.surname,
SUBSTRING(cd.birthdate,6),
cd.email
FROM client_contacts AS cd
JOIN clients AS c ON c.id = cd.client_id
WHERE SUBSTRING(birthdate,6) = '07-20';
Are there better ways to do this query than the one I did above?
You could set your where clause to:
WHERE
DATE_PART('day', birthdate) = date_part('day', CURRENT_DATE)
AND
DATE_PART('month', birthdate) = date_part('month', CURRENT_DATE)
In case it matters, the age function will let you work around the issue of leap years:
where age(cd.birthdate) - (extract(year from age(cd.birthdate)) || ' years')::interval = '0'::interval
It case you want performance, you can actually wrap the above with an arbitrary starting point (e.g. 'epoch'::date) into a function, too, and use an index on it:
create or replace function day_of_birth(date)
returns interval
as $$
select age($1, 'epoch'::date)
- (extract(year from age($1, 'epoch'::date)) || ' years')::interval;
$$ language sql immutable strict;
create index on client_contacts(day_of_birth(birthdate));
...
where day_of_birth(cd.birthdate) = day_of_birth(current_date);
(Note that it's not technically immutable, since dates depend on the timezone. But the immutable part is needed to create the index, and it's safe if you're not changing the time zone all over the place.)
EDIT: I've just tested the above a bit, and the index suggestion actually doesn't work for feb-29th. Feb-29th yields a day_of_birth of 1 mon 28 days which, while correct, needs to be added to Jan-1st in order to yield a valid birthdate for the current year.
create or replace function birthdate(date)
returns date
as $$
select (date_trunc('year', now()::date)
+ age($1, 'epoch'::date)
- (extract(year from age($1, 'epoch'::date)) || ' years')::interval
)::date;
$$ language sql stable strict;
with dates as (
select d
from unnest('{
2004-02-28,2004-02-29,2004-03-01,
2005-02-28,2005-03-01
}'::date[]) d
)
select d,
day_of_birth(d),
birthdate(d)
from dates;
d | day_of_birth | birthdate
------------+---------------+------------
2004-02-28 | 1 mon 27 days | 2011-02-28
2004-02-29 | 1 mon 28 days | 2011-03-01
2004-03-01 | 2 mons | 2011-03-01
2005-02-28 | 1 mon 27 days | 2011-02-28
2005-03-01 | 2 mons | 2011-03-01
(5 rows)
And thus:
where birthdate(cd.birthdate) = current_date
The #Jordan answer is correct but, it wont work if your date format is string. If it is string you have type cast it using to_date function. then apply the date_part function.
If date of birth (DOB) is 20/04/1982 then the query is:
SELECT * FROM public."studentData" where date_part('day',TO_DATE("DOB", 'DD/MM/YYYY'))='20'
AND date_part('month',TO_DATE("DOB", 'DD/MM/YYYY'))='04';
or
EXTRACT(MONTH FROM TO_DATE("DOB", 'DD/MM/YYYY'))='04' AND EXTRACT(DAY FROM TO_DATE("DOB", 'DD/MM/YYYY'))='20'
I add double quotes to table name("studentData") and field name ("DOB") because it was string.
Credit to #Jordan
WHERE date_part('month', cd.birthdate) = '07' AND date_part('day', cd.birthdate) = '20'
you can read more about this here
Try with something like:
WHERE EXTRACT(DOY FROM TIMESTAMP cd.birthdate) = EXTRACT(DOY FROM TIMESTAMP CURRENT_TIMESTAMP)
The best way IMO is to use to_char(birthday, 'MM-DD') in (?) where you just give some date range mapped to 'MM-DD' in place of ?. Unless you have to support very big date ranges this solution is very simple, clean and bug resistant.
What you are trying to do is, extract the person detail who would be wished using SQL manually, and send the wish separately manually. What if I suggest you a better approach?
Extract the wish details as excel and let wishing app take care of everything.
At minimal it just need two things excel file with wish details (Date, name, email) and a configuration file (application.properties) and that is it, you are good to go.
Further there various options to run the application locally (Command line, foreground, background, docker, windows scheduler, unix cron etc) Cloud.
Application is highly configurable , you can configure various details like:
Workbook loading options
Image options to send with wishes.
SMTP Configurations
Other application level configurations like, when to send wish, belated wish, logging etc.
Disclaimer : I am the owner of the application

Categories