event schedule php MySQL keeping track of upcoming events - php

i have been working on event schedule with php and MySQL my goal is to be able to have the background of a website change for each event such as Halloween Christmas and so on i have come up with one that will work with the month but i am needing it to workout the day to ignoring the year
<?php
$con = mysql_connect(MYSQL_host,MYSQL_username,MYSQL_password);
mysql_select_db(MYSQL_Database, $con);
$result = mysql_query('SELECT * FROM Event_Schedule WHERE MONTH(Start) <= MONTH(NOW()) AND MONTH(End) >= MONTH(NOW())') or die('Query failed: ' . mysql_error());
$Edit_theme_row = mysql_fetch_array($result)
?>
i have tried adding Day in to the code
$result = mysql_query('SELECT * FROM Event_Schedule WHERE (MONTH(Start) <= MONTH(NOW()) AND DAY(Start) <= DAY(NOW())) AND (MONTH(End) >= MONTH(NOW()) AND DAY(End) >= DAY(NOW()))') or die('Query failed: ' . mysql_error());
$Edit_theme_row = mysql_fetch_array($result)
?>
But seem to ignore event
using template DATE in MySQL
example
2015-10-28 to 2015-11-02 halloween
2015-12-01 to 2015-12-26 christmas
ignoring the year so each year it will change on that month and day

i hope that i understand your problem correctly. The first thing i have seen is that you use functions in the WHERE on the database fields. This is not a good idea. So MySQL must read every record (FULL TABLE SCAN) to do this and cant use an index for this.
The second thing is that you not normalize the start and end date of each event in 2 separate fields to do an easy compare. You can store the dates from the application in second fields with an normalized year ie. '1970' so you can easy compare it or you use PERSISTENT fields in MySQL then MySQL can do it for you.
Here a Sample
CREATE TABLE `table1` (
`nr` int(11) unsigned NOT NULL AUTO_INCREMENT,
`event_name` varchar(32) DEFAULT NULL,
`event_start` date NOT NULL DEFAULT '0000-00-00',
`event_end` date NOT NULL DEFAULT '0000-00-00',
`norm_start` date AS ( date_format(event_start,'1970-%m-%d') ) PERSISTENT,
`norm_end` date AS ( date_format(event_end,'1970-%m-%d') ) PERSISTENT,
PRIMARY KEY (`nr`),
KEY `event_start` (`event_start`,`event_end`),
KEY `norm_start` (`norm_start`,`norm_end`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Now we insert a row
INSERT INTO `table1`
( `event_name`, `event_start`, `event_end`)
VALUES
('hallo', '2015-10-31', '2015-10-31');
The Reseult
MariaDB > select * from table1;
+----+------------+-------------+------------+------------+------------+
| nr | event_name | event_start | event_end | norm_start | norm_end |
+----+------------+-------------+------------+------------+------------+
| 4 | hallo | 2015-10-31 | 2015-10-31 | 1970-10-31 | 1970-10-31 |
+----+------------+-------------+------------+------------+------------+
1 row in set (0.00 sec)
Now you can directly compare the dates
SELECT *
FROM table1
WHERE date_format(now(),'1970-%m-%d')
BETWEEN norm_start AND norm_end;
So you can the events. The only thing is when a event overlaps a year ( 2015-12-30 - 2016-01-07 ) you mus put 2 rows in the eventtable.
Please let me now if this wars what you want

Related

check dates on database

On my database table I have 2 columns, start_date and end_date.
Sample data would be:
-------------------------------
start_date | end_date
-------------------------------
2017-11-01 2017-11-02
2017-11-03 2017-11-07
2017-11-20 2017-11-28
2017-11-13 2017-12-02
-------------------------------
I need to find if there are 5 consecutive days that are not yet used, which in this case, there is:
(2017-11-08 to 2017-11-13)
I'm using PHP and MySQL.
Thanks in advance!
You'd need to check for edge cases depending on your actual data and if there were no overlap dates, but this is a good start for the provided data.
Assuming table and data as defined as below:
CREATE TABLE
`appointments`
(
`appointment_id` INT PRIMARY KEY AUTO_INCREMENT,
`start_date` DATE,
`end_date` DATE
);
INSERT INTO
`appointments`
(`start_date`, `end_date`)
VALUES
('2017-11-01', '2017-11-02'),
('2017-11-03', '2017-11-07'),
('2017-11-20', '2017-11-28'),
('2017-11-13', '2017-12-02');
If you order the rows, and take the lag from the end date before it, and take any gaps of 5 or more. In SQL Server there are LAG functions, but here's a way of doing the same. Then once you have a table of all rows and their corresponding gaps, you take the start date of that period, and create the gap period from the number of days between. Since TIMESTAMPDIFF is inclusive, you need to subtract a day.
SET #end_date = NULL;
SELECT
DATE_ADD(`start_date`, INTERVAL -(`gap_from_last`-1) DAY) AS `start_date`,
`start_date` AS `end_date`
FROM
(
SELECT
`appointment_id`,
CASE
WHEN #end_date IS NULL THEN NULL
ELSE TIMESTAMPDIFF(DAY, #end_date, `start_date`)
END AS `gap_from_last`,
`start_date`,
#end_date := `end_date` AS `end_date` -- Save the lag date from the row before
FROM
`appointments`
ORDER BY
`start_date`,
`end_date`
) AS `date_gap` -- Build table that has the dates and the number of days between
WHERE
`gap_from_last` > 5;
Provides:
start_date | end_date
------------------------
2017-11-08 | 2017-11-13
Edit: Oops! Forgot the SQLFiddle (http://sqlfiddle.com/#!9/09cfce/16)
SELECT x.end_date + INTERVAL 1 DAY unused_start
, MIN(y.start_date) unused_end
FROM appointments x
JOIN appointments y
ON y.start_date >= x.end_date
GROUP
BY x.start_date
HAVING DATEDIFF(MIN(y.start_date),unused_start) >= 5;

Selecting a datetime data and getting only the day?

I have a datetime column in my database and want to echo out how many users regisetered today.
id | register_date
1 | 2014-04-16 09:55:13
2 | 2014-04-14 19:23:49
$sql_users = "SELECT * FROM users";
$result_users = mysql_query($sql_users);
I thought that I could check every single data in it by using date('d', $register_time ) in a while statement. Is there any easier way to do it?
Use MySQL's DATE() and CURDATE() functions:
SELECT COUNT(*) FROM users WHERE DATE(register_date) = CURDATE()

writing a row for each day. mySQL

i've a web form, the user input two dates (YYYY/MM/DD) representing a interval and other informations about an activity on a day.
EXAMPLE: he select 2013/09/12 to 2013/10/02 activity: Swimming
in that case my table will look like:
date | activity
2013/09/12 | swimming
2013/09/13 | swimming
2013/09/14 | swimming
2013/09/15 | swimming
2013/09/16 | swimming
and so on....
i've to write a row with the activity for every day of the date inveral provided by the user
can i do this without iterate through days manually?
i'm using php+mysqli
EDIT: i can't use two columns for start and end date
I think it is better to make two columns (e.g start_day & end_day).
If it is not possible to change your DB construction you can try this:
PHP:
$last_date = $start_date;
$ready = false;
while ($ready === false) {
$last_date = date('Y-m-d', strtotime($last_date . ' + 1 day'));+
// add $last_date to your mysql table here
if ($last_date == $stop_date) {
$ready = true;
}
}
It's untested but I hope it works ;)
Use 2 different date columns in your table; one for the start date and one for the end date, you can then add the beginning and end dates of the activity to each of these respectively.
i can give You a clue if You can use PROCEDURES:
DELIMITER $$
DROP PROCEDURE IF EXISTS `dowhile_thing`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `dowhile_thing`(dt_start DATE,dt_stop DATE, thing CHAR(20))
BEGIN
DECLARE v1 INT DEFAULT 0;
CREATE TEMPORARY TABLE tmp (
`day_name` VARCHAR(256) DEFAULT NULL,
`date_change` DATE DEFAULT NULL,
thing CHAR(20)
) ENGINE=MYISAM DEFAULT CHARSET=utf8 ;
SELECT TIMESTAMPDIFF(DAY, dt_start, dt_stop)+1 INTO v1;
WHILE v1 > -1 DO
INSERT tmp (SELECT DAYNAME( ADDDATE(dt_start, INTERVAL v1 DAY) ),ADDDATE(dt_start, INTERVAL v1 DAY),thing );
SET v1 = v1 - 1;
END WHILE;
SELECT * FROM tmp;
DROP TEMPORARY TABLE IF EXISTS tmp;
END$$
DELIMITER ;
and then call:
CALL dowhile_thing('2013-06-10','2013-06-14','swim');
result:
day_name | date_change | thing
Saturday | 2013-06-15 | swim
Friday | 2013-06-14 | swim
...

SQL / PHP: get all results within time X to Y, and detect if there are available times inbetween

Sorry if the title is a bit vague..
I have a database looking like this:
orderid | roomname | date(DATE) | from(TIME) | to(TIME)
Example-data:
1231 | E12 | 2013-04-05 | 07:00:00 | 10:00:00
1671 | E12 | 2013-04-05 | 13:00:00 | 14:00:00
I'm for example searching up a certain date and obviously getting all reservations on that day.
As you can see on the example-data, the room is available between 10:00:00 and 13:00:00. How can I catch this?
I was thinking about looping through time 07:00:00-16:00:00 (with one query for each) and check if I get any results from sql. If I do get results, I will know that the room is busy, but since there are unknowns here (ex. 08:00:00 and 09:00:00 doesn't exists), I will get false-positives on this.
Any tips here?
One way would be using a 'calendar table', or if you're only ever interested in one day a 'clock table' would do. The following illustrates (roughly) how you'd use it.
SELECT clock.time AS available
FROM clock
LEFT JOIN bookings ON clock.time BETWEEN bookings.from AND bookings.to
AND bookings.date = '2013-01-01'
WHERE bookings.id IS NULL
http://www.brianshowalter.com/calendar_tables is an example of how to create a calendar in MySQL
With this data:
create table rooms
(
orderid int not null,
roomname varchar(8) not null,
date date not null,
`from` time not null,
`to` time not null
);
insert into rooms values (1231, 'E12', '2013-04-05', '07:00', '10:00');
insert into rooms values (1671, 'E12', '2013-04-05', '13:00', '14:00');
to get the available time interval/slot, you can issue this query:
SELECT DATE_FORMAT(r1.`to`, '%T') AS `From`, DATE_FORMAT(min(r2.`from`), '%T') AS `To`
FROM
rooms r1 JOIN rooms r2
ON r1.`to`< r2.`from`
WHERE r1.date = '2013-04-05' AND r1.roomname = 'E12'
GROUP BY r1.`to`
HAVING
NOT EXISTS (SELECT NULL FROM rooms r3
WHERE r1.`to` < r3.`to`
AND min(r2.`from`) > r3.`from`)
the above query will return:
10:00:00 13:00:00
Here's the SQL fiddle: http://sqlfiddle.com/#!2/3c124/25
Note: the above query was kindly adapted from this answer by #fthiella:
https://stackoverflow.com/a/14139835/114029
With this additional query:
SELECT (COUNT(*) = 0) AS Available
FROM rooms
WHERE roomname = 'E12' AND date = '2013-04-05' AND
(
(`from` < MAKETIME(10,00,00) AND `to` > MAKETIME(10,00,00)) OR
(`from` < MAKETIME(13,00,00) AND `to` > MAKETIME(13,00,00))
)
It'll return 1, that is, there's no reservation between the given start time (from) and end time (to) and so the room is available.
Here's the SQL Fiddle to play with the data: http://sqlfiddle.com/#!2/3c124/1

Why do i get this result?

SELECT *
FROM afspraken
WHERE user_id = '2'
AND datum > '2012-06-05'
OR (
user_id = '2'
AND datum = '2012-06-05'
AND begintijd >= '22:47'
)
ORDER BY datum DESC , begintijd ASC
This above is my query.. And while i should get zero result i still get one which is:
id user_id datum begintijd opmerking
114 2 2012-06-05 9:30 Deze afspraak is online gemaakt.
Now if i have this correctly, this query has 2 options to give results.. which is:
The user_id must be the same AND the date has to be higher then 2012-06-05.. Since its the same date this won't give the result..
Now the second option which is when the user_id is the same, the date is the same and when the beginningtime is the same or higher.. Now the time in the query shown is 22:47.. The time in the database is 9:30 morning.. How is 9:30 morning higher or equal to 22:47??
id int(10)
user_id int(10)
datum date
begintijd varchar(5)
opmerking varchar(8000)
reminder int(10)
It looks like your begintijd column is a varchar column.
So, as strings, '22:47' < '9:30'.
A solution would be to convert your begintijd column to a time datatype.
If you are able to change your database layout why not use DATETIME like this:
id int(10)
user_id int(10)
afspraak_dt datetime
opmerking varchar(8000)
reminder int(10)
Your data:
id user_id afspraak_dt opmerking
114 2 2012-06-05 9:30 Deze afspraak is online gemaakt.
Examples selects:
SELECT * FORM afspraken WHERE user_id = 2 AND afspraak_dt > '2012-06-05 22:47'
Select all afspraken on that day for user id 2
SELECT * FORM afspraken WHERE user_id = 2 AND DATE(afspraak_dt) = '2012-06-05'
Select whith unix timestamp (select all afspraken in the future for user 2)
SELECT * FROM afspraken WHERE user_id = 2 AND UNIX_TIMESTAMP(afspraak_dt) > NOW()
The MySQL datetime has numerous select options for handling date and time. See http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
The idea would be to cast your time columns and values to Time:
SELECT CAST('20:05' AS Time) > CAST('9:06' AS Time) #returns 1 (compares times - what you want)
SELECT '20:05' > '9:06' #returns 0 (compares strings - not what you want)
Read more here.

Categories