This SQL is called by a Smarty File designed to download an .xlsx of the output. It works well for all months EXCEPT the Dec. (end of year) report. Something is needed to get it to cross the year-end boundary but I can't figure what. ? Thanks.
SELECT user_id, cert_name, from_email, created_at, phone as role,
delivery, user_street, user_city, user_state, user_zip,
user_country_id, standard_fee, expedited_fee
FROM support_tickets
WHERE nature = 2
AND user_id IS NOT NULL
AND created_at BETWEEN '2012-12-05 04:00:01' and date(concat_ws('-', #year, #month + 1, 1))
ORDER BY created_at DESC
Use date arithmetic, not string concatenation.
If you try to add #month+1 when month is 12, you get month 13, not month 1 of the next year. There is no month 13 in calendars currently in use.
For your case I would recommend using the LAST_DAY() function that is built into MySQL. This returns the last date in the current month of its argument.
Example:
mysql> SELECT LAST_DAY('2020-12-05') AS last;
+------------+
| last |
+------------+
| 2020-12-31 |
+------------+
I suspect you want the last day of the same month.
If you really want the first day of the next month, use date arithmetic:
mysql> SELECT LAST_DAY('2020-12-05') + INTERVAL 1 DAY AS next;
+------------+
| next |
+------------+
| 2021-01-01 |
+------------+
Related
I have this certain problem about mysql date functions.
I'm trying to compare the value of THIS MONTH to the given timestamp in database.
For example, month today is june, and the timestamp is 1369967316
And I'm trying to determine if that timestamp is in month of june.
$query = db_query("SELECT * FROM users WHERE MONTH(FROM_UNIXTIME(CURDATE())) = MONTH(1369967316)");
//count total members this mont
$members_month = $query->rowCount();
so if I used the rowCount, the $members_month should have the value of 1.
Unfortunately it doesn't work.
Any help would be appreciated.
Well I saw some answers that some kind of relevant to mine but it doesn't hit the spot or I didn't applied it well.
mysql get month from timestamp not working
how to use curdate() in where clause against unixtimestamp (bigint) column
This works for me:
mysql> SELECT MONTH(FROM_UNIXTIME(1369967316));
+----------------------------------+
| MONTH(FROM_UNIXTIME(1369967316)) |
+----------------------------------+
| 5 |
+----------------------------------+
Your issue is likely coming from the fact that 1369967316 is May 30th, not June (as you expect), thus resulting in an inequality with MONTH(CURDATE()).
mysql> SELECT FROM_UNIXTIME(1369967316);
+---------------------------+
| FROM_UNIXTIME(1369967316) |
+---------------------------+
| 2013-05-30 22:28:36 |
+---------------------------+
I have a table with a kind of weird date format in a column as varchar - this is the format that the company has provided me with - the T in the middle seems to mess things up.
EVENTID | EVENT_DATE | EVENT_DURATION
1 | 2012-10-14T06:00 | 15
2 | 2012-10-14T06:15 | 11
3 | 2012-10-14T06:26 | 14
4 | 2012-10-14T06:40 | 10
ect...ect
I have php code to return the current time in the exact same format (with the weird 'T' in the middle'
$thisin = DateTime::createFromFormat('Y-m-d\TH:i', date('Y-m-d\TH:i'));
$thisin->setTimeZone(new DateTimeZone('UTC'));
$thisout= $thisin->format('Y-m-d\TH:i');
Assuming that today is the 14th and the current time is 06:21, how do i query the current row based on duration that matches "$thisout from php" and the next five rows (in the future).
Because the current time and date are returned from php as "2012-10-14T06:21" The query should output
2 | 2012-10-14T06:15 | 11 (Now SHowing)
3 | 2012-10-14T06:26 | 14
4 | 2012-10-14T06:40 | 10
ect ect
I have been scratching my head for hours, DATE_FORMAT() Doesn't seem to work, and I think it may be the T in the middle. I am aslo have to figure out how to use duration to determine if the current time applies to a specific row.
This does not work
SELECT DISTINCT EVENTID, EVENT DATE, EVENT_DURATION
FROM epg_event
WHERE DATE_FORMAT(EVENT_DATE, '%Y-%m-%dT%H:%i') >= DATE_FORMAT(NOW(), '%Y-%m-%dT%H:%i')
ORDER BY EVENT_DATE ASC LIMIT 5
Any Ideas?
You should load the date information into a Date column rather than a varchar column in the database. As previously noted this is the ISO format for dates.
Need to add in the interval.
where event_date + INTERVAL duration MINUTE >= NOW()
I'm not currently able to test it, but something like this might work:
SELECT DISTINCT EVENTID, EVENT_DATE, EVENT_DURATION
FROM epg_event
WHERE (event_date <= NOW()) AND (ADDTIME(event_date, INTERVAL event_duration MINUTE) >= NOW())
ORDER BY event_date ASC LIMIT 5
DATE_FORMAT() is meant for formatting a DATETIME field, not the other way around. And, as mentioned earlier, you event_date should be a DATETIME field and you should convert the time when you import the data to your database.
I'm building a simple availability calendar with PHP and MySQL.
I have a table which stores the available dates for a property (currently all of them are blocks of 7 days)
available_dates:
start_date DATE
end_date DATE
available_id INT PRIMARY KEY
property_id INT
booked TINYINT(1)
And a table of booked dates which references the available_id of my available_dates table:
bookings
booking_id INT
available_id INT
***user details***
I plan on having rows added to available_dates for each property to mark which dates can be booked, and then setting the booked flag on that table when somebody books that block.
What I'd like to do is show a list of dates (in blocks of x days, 7 in this case) that have no availability set - so the date does not appear in that table - for the next 24 months or so.
I'm having trouble wrapping my head around this and I know there is a simpler way to do it that my first ideas of looping through each property, then each block of 7 days, etc etc.
Can anyone enlighten me?
Update:
Thanks to #ZaneBien 's brilliant and comprehensive answer, I've managed to get the results I need by using his yeardate table & procedure.
What I've done is when the page that needs to show the dates with no availability set is requested, the PHP will call the procedure to add more yeardates if there aren't any for CURYEAR()+2.
Then to get my results, a slightly modified version of Zane's query:
SELECT
a.yeardate AS blockstart,
DATE_ADD(a.yeardate, INTERVAL 7 DAY) AS blockend
FROM
yeardates a
LEFT JOIN
available_dates b
ON(a.yeardate BETWEEN b.start_date AND b.end_date)
OR
(DATE_ADD(a.yeardate, INTERVAL 7 DAY) BETWEEN b.start_date AND b.end_date)
WHERE
b.date_id IS NULL AND WEEKDAY(a.yeardate)=5;
In my case, the blocks are of 7 days, saturday to saturday - so I added the second WHERE clause to the query so that I get distinct 1 week saturday to saturday blocks for each row, that happen one after the other.
So instead of:
+------------+------------+
| blockstart | blockend |
+------------+------------+
| 2012-01-01 | 2012-01-08 |
| 2012-01-02 | 2012-01-09 |
| 2012-01-03 | 2012-01-10 |
| 2012-01-04 | 2012-01-11 |
I get this:
+------------+------------+
| blockstart | blockend |
+------------+------------+
| 2012-01-07 | 2012-01-14 |
| 2012-01-14 | 2012-01-21 |
| 2012-01-21 | 2012-01-28 |
| 2012-01-28 | 2012-02-04 |
Which is exactly what I need. Thanks again to Zane for a great answer.
Understanding your question as Retrieve all 7 day interval blocks of the current and next year whose ranges do not overlap any interval blocks already existing in the available_dates table:
To work with all days of the current and next year, we have to create a separate table (yeardates) containing DATEs of all days of the current and next year. This will facilitate our OUTER JOIN operation in the retrieval query.
Code to define the yeardates table and insert dates:
CREATE TABLE yeardates
(
yeardate DATE NOT NULL,
PRIMARY KEY (yeardate)
) ENGINE = MyISAM;
DELIMITER $$
CREATE PROCEDURE PopulateYear(IN inputyear INT)
BEGIN
DECLARE i INT;
DECLARE i_end INT;
SET i = 1;
SET i_end = CASE WHEN inputyear % 4 THEN 365 ELSE 366 END;
START TRANSACTION;
WHILE i <= i_end DO
INSERT INTO yeardates VALUES (MAKEDATE(inputyear, i));
SET i = i + 1;
END WHILE;
COMMIT;
END$$
DELIMITER ;
CALL PopulateYear(2012);
CALL PopulateYear(2013);
The table is then created and contains all days of the current and next year. If we ever need to insert days for subsequent years, just CALL the procedure again with the year as the parameter (e.g. 2014, 2015, etc..).
Then we can get the 7-day blocks that don't overlap blocks in the available_dates table:
SELECT
a.yeardate AS blockstart,
DATE_ADD(a.yeardate, INTERVAL 7 DAY) AS blockend
FROM
yeardates a
LEFT JOIN
available_dates b ON
(a.yeardate BETWEEN b.start_date AND b.end_date)
OR
(DATE_ADD(a.yeardate, INTERVAL 7 DAY) BETWEEN b.start_date AND b.end_date)
WHERE
b.available_id IS NULL
That retrieves all free 7-day blocks based on the bookings of all properties, but if we need to get the free 7-day blocks for just a particular property, we can use:
SELECT
a.yeardate AS blockstart,
DATE_ADD(a.yeardate, INTERVAL 7 DAY) AS blockend
FROM
yeardates a
LEFT JOIN
(
SELECT *
FROM available_dates
WHERE property_id = <property_id here>
) b ON
(a.yeardate BETWEEN b.start_date AND b.end_date)
OR
(DATE_ADD(a.yeardate, INTERVAL 7 DAY) BETWEEN b.start_date AND b.end_date)
WHERE
b.available_id IS NULL
Where <property_id here> is the property_id. We can even do the selection based on multiple properties at a time by simply changing it to WHERE property_id IN (<comma sep'd list of property_ids here>).
I think youve got it backwards.
All dates are potentially available unless booked, record what has been booked in the database and knock those out of your results
While making a sample details page, I just stuck upon a really confusing situation. What i actually want to do is like this:
+----------------------------------------------------+
+ Year | Month | Date | Total Gain +
+----------------------------------------------------+
+ 2003 | January | 26/01/2003 | +90 % +
+ 2003 | January | 27/01/2003 | +10 % +
+ 2003 | Feburary| 01/02/2003 | -29 % +
+ 2003 | Feburary| 15/02/2003 | +0.52 % +
+----------------------------------------------------+
What I actually want is that I can list the Month names and year wise like mysql_query('SELECT month FROM mytable WHERE year="2003"');
But the problem is it shows January two time. I want to display January one time and a link next to it which will carry to the next page. This will show the stats of January.
Maybe you should use a GROUP BY clause and calculates your Total gain as well.
(Since the table structure is not specified, I'll guess here)
SELECT `Year`, `Month`, SUM(gain) AS 'Total Gain +' FROM table GROUP BY month, year;
I think what youre looking for is DISTINCT query, ie
SELECT DISTINCT year, month FROM mytable
I'm writing a PHP competition script for a members site that needs to restrict entries to one per day per member. So far I have the following MySQL code:
SELECT ce_id
FROM competition_entries
WHERE ce_c_id = '$c_id'
AND ce_sub_id = '$user_id'
AND cte_date >= SYSDATE() - INTERVAL 1 DAY
ce_c_id is the competition ID,
ce_sub_id is the member ID, and
cte_date is a MYSQL datetime stamp for the entry.
It's hard for me to test from where I am now & I need to find a solution, so I'm hoping someone can tell me whether this is restricting to once-per-day or once-per-24hrs - and point me in the right direction if it's the latter.
TIA :)
Create a primary key composed of the user_id, competition_id and a date type column.
To check if the user has already placed an entry:
select count(*)
from competition_entries
where ce_c_id = '$c_id'
AND ce_sub_id = '$user_id'
AND cte_date = current_date()
I'm hoping someone can tell me whether this is restricting to once-per-day or once-per-24hrs
Looks like it's 24 hours:
mysql> select sysdate(), sysdate() + interval 1 day;
+---------------------+----------------------------+
| sysdate() | sysdate() + interval 1 day |
+---------------------+----------------------------+
| 2011-03-21 15:50:56 | 2011-03-22 15:50:56 |
+---------------------+----------------------------+
1 row in set (0.01 sec)
If you need "tomorrow", as in, tonight at one minute past 23:59, consider chomping down things to plain old DATE's resolution:
mysql> select DATE(sysdate()), DATE(sysdate()) + interval 1 day;
+-----------------+----------------------------------+
| DATE(sysdate()) | DATE(sysdate()) + interval 1 day |
+-----------------+----------------------------------+
| 2011-03-21 | 2011-03-22 |
+-----------------+----------------------------------+
1 row in set (0.00 sec)
By just considering dates instead of times, your cutoff will effectively expire at midnight. Watch out, though -- you'll then be at the mercy of the time on your MySQL server, which might differ from the time on your application server if they are on different machines.
Can't be sure without testing, but I'd hazard a guess that it's once every 24h.
Try the following instead:
SELECT ce_id FROM competition_entries WHERE ce_c_id = '$c_id' AND ce_sub_id = '$user_id' AND DATE(cte_date) == DATE(SYSDATE())
Here you are clearly comparing two dates, one from your field and the other from the current date for equality.