How to make it to select from 1st day every month - php

Hello there I have a question so I have a goal mysqli query and it sum the price and select by interval 1 month I try few things to made it to select only from 1st day of the month but I have no idea anymore how to do it..
So here is my code
$monthquery=mysqli_query($link,"SELECT SUM(price) FROM `transactions` WHERE `date` BETWEEN date_sub(CAST(CURRENT_TIMESTAMP AS DATE),INTERVAL 1 MONTH) AND CAST(CURRENT_TIMESTAMP AS DATE);")->fetch_assoc();
$month = $monthquery["SUM(price)"];
$percent = 0;
$percent = ($month*100)/$donation_goal;
$goal = round($percent, 2);
I want it to select let say If the customer start from 20/12/2019 and everything have to be reset on 01/01/2020, not like now from 20th to 20th.. I saw few things here on stackoverflow I try them and it does not always it give me same result.
Thanks anyone.

select only from 1st day of the month
You can do:
`date` >= DATE_FORMAT(NOW() ,'%Y-%m-01')

Related

Calculate the difference b/w two months data

I have a mysql table orders in that I have a column order_date which is current time stamp(2016-08-17 00:00:00.000000). now I want to select or count the data's entered this month and the previous month, after this I can find the difference between these two months I am using this code and it is not working.
$sql="SELECT * FROM order WHERE order_date > DATE_SUB(NOW(), INTERVAL 1 MONTH)";
$result = $this->db->query($sql);
return $result;
this is not working an mysql error is produced.
Try
$sql="SELECT * FROM order WHERE DATE(order_date) LIKE DATE_SUB(CURDATE(), INTERVAL 1 MONTH)";
$result = $this->db->query($sql);
return $result;
i think this Link[http://sqlhints.com/2015/07/10/how-to-get-difference-between-two-dates-in-years-months-and-days-in-sql-server/] will help you
Use this. Hope it helps what you want. Thanks
$todayDate = date('Y-m-d');
$todayMonth = date("m", strtotime($todayDate ));
$previousMonth = $todayMonth - 1;
$sql = "SELECT * FROM order WHERE MONTH(order_date) BETWEEN '$todayMonth' AND '$previousMonth'";
First, the following is the correct logic to get all values from the current month and all of the previous month:
select *
from orders o
where order_date >= date_sub(date_sub(curdate(), interval day(curdate) - 1 day), interval 1 month);
Then, use conditional aggregation for comparison. Here is an easy way:
select sum(month(order_date) = month(curdate())) as cur_month,
sum(month(order_date) <> month(curdate())) as prev_month,
(sum(month(order_date) = month(curdate())) -
sum(month(order_date) <> month(curdate()))
) as diff
from orders o
where order_date >= date_sub(date_sub(curdate(), interval day(curdate) - 1 day), interval 1 month);
Note: I don't fully see the utility of comparing a partial month (this month) to a full month (last month), but that is what you seem to be asking for. If you are asking for something different, then ask another question with sample data and desired results.

Working out the amount of free dates in a given time period

I have a fun one for you. I have a database with the date columns free_from and free_until. What I need to find is the amount of days between now and 1 month today which are free. For example, if the current date was 2013/01/15 and the columns were as follows:
free_from | free_until
2013/01/12| 2013/01/17
2013/01/22| 2013/01/26
2013/01/29| 2013/02/04
2013/02/09| 2013/02/11
2013/02/14| 2013/02/17
2013/02/19| 2013/02/30
The answer would be 16
as 2 + 4 + 6 + 2 + 2 + 0 = 16
The first row only starts counting at the 15th rather than the 12th
since the 15th is the current date.
The last row is discounted because none of the dates are within a
month of the current date.
The dates must be counted as it the free_from date is inclusive and
the free_until date is exclusive.
I'm assuming DATEDIFF() will be used somewhere along the line, but I can't, for the life of me, work this one out.
Thanks for your time!
Edit: This is going into PHP mysql_query so that might restrict you a little concerning what you can do with MYSQL.
SET #today = "2013-01-15";
SET #nextm = DATE_ADD(#today, INTERVAL 1 month);
SET #lastd = DATE_ADD(#nextm, INTERVAL 1 day);
SELECT
DATEDIFF(
IF(#lastd> free_until, free_until, #lastd),
IF(#today > free_from, #today, free_from)
)
FROM `test`
WHERE free_until >= #today AND free_from < #nextm
That should work. At least for your test data. But what day is 2013/02/30? :-)
Dont forget to change #today = CURDATE();
The best I can think of is something like:
WHERE free_until > CURDATE()
AND free_from < CURDATE() + INTERVAL '1' MONTH
That will get rid of any unnecessary rows. Then on the first row do in PHP:
date_diff(date(), free_until)
On the last row, do:
date_diff(free_from, strtotime(date("Y-m-d", strtotime($todayDate)) . "+1 month"))
Then on intermediate dates do:
date_diff(free_from, free_until)
Something to that effect, but this seems extremely clunky and convoluted...
From the top of my mind... first do a:
SELECT a.free_from AS a_from, a.free_until AS a_until, b.free_from AS b_from
FROM availability a
INNER JOIN availability b ON b.free_from > a.free_until
ORDER BY a_from, b_from
This probably will return a set of rows where for each row interval you have next i.e. greater intervals. The results are ordered strategically. You can then wrap the results in a partial group by:
SELECT * FROM (
SELECT a.free_from AS a_from, a.free_until AS a_until, b.free_from AS b_from
FROM availability a
INNER JOIN availability b ON b.free_from > a.free_until
ORDER BY a_from, b_from
) AS NextInterval
GROUP BY a_from, b_until
In the above query, add a DATE_DIFF clause (wrap it in SUM() if necessary):
DATE_DIFF(b_until, a_from)

SQL Query Concerning Dates

I have the following relation in my schema:
Entries:
entryId(PK) auto_inc
date date
In order to count the total entries in the relation I use a query in my php like this:
$sql = mysql_query("SELECT COUNT(*) as Frequency FROM Entries WHERE date = '$date'");
My question is how can I count the number of entries for the CURRENT month..
You want a between query based on your date column.
WHERE date BETWEEN startdate AND enddate.
Between is equivalent to date >= startdate AND date <= enddate. It would of course be also possible to just use >= AND < explicitly which would simplify it a bit because you don't need to find the last day of the month, but just the first day of the following month using only DATE_ADD(..., INTERVAL 1 MONTH).
However startdate and enddate in this case would be derived from CURDATE().
You can use CURDATE(), MONTH(), DATE_ADD and STR_TO_DATE to derive the dates you need (1st day of current month, last day of current month). This article solves a similar problem and all the techniques needed are shown in examples that you should be able to adapt:
http://www.gizmola.com/blog/archives/107-Calculate-a-persons-age-in-a-MySQL-query.html
The first day of the current month is obvious YEAR-MONTH(CURDATE())-01. The last day you can calculate by using DATE_ADD to add 1 Month to the first day of the current month, then DATE_ADD -1 Days.
update-
Ok, I went and formulated the full query. Don't think str_to_date is really needed to get the index efficiency but didn't actually check.
SELECT count(*)
FROM entries
WHERE `date` BETWEEN
CONCAT(YEAR(CURDATE()), '-', MONTH(CURDATE()), '-', '01')
AND
DATE_ADD(DATE_ADD(CONCAT(YEAR(CURDATE()), '-', MONTH(CURDATE()), '-', '01'), INTERVAL 1 MONTH), INTERVAL -1 DAY);
Try this
SELECT COUNT(1) AS `Frequency`
FROM `Entries`
WHERE EXTRACT(YEAR_MONTH FROM `date`) = EXTRACT(YEAR_MONTH FROM CURDATE())
See EXTRACT() and CURDATE()
Edit: Changed NOW() to CURDATE() as it is more appropriate here
Try
$sql = mysql_query("SELECT COUNT(*) as Frequency FROM Entries WHERE MONTH(date) = MONTH(NOW()) );

PHP and MYSQL having issues with my query!

I am having some issues with the following query, the issue is that I need it so it displays the courses for the current day until the end of the day not just till the start of the day like it does currently. Basically users cannot access the course if they are trying to access the course on its enddate so i need to some how make it so that they can still access it for 23 hrs 59 mnutes and 59 seconds after the end date I think I have to add some sort of time to the NOW() to accomplish this but im not sure how to go about this.The query is as follows:
if ($courses = $db->qarray("
SELECT `CourseCode` AS 'code' FROM `WorkshopUserSessions`
LEFT JOIN `WorkshopSession` ON (`WorkshopUserSessions`.`sessionid` = `WorkshopSession`.`id`)
LEFT JOIN `WorkshopCourses` ON (`WorkshopSession`.`cid` = `WorkshopCourses`.`cid`)
WHERE `WorkshopUserSessions`.`userid` = {$info['uid']} AND `WorkshopUserSessions`.`begindate` <= NOW() AND `WorkshopUserSessions`.`enddate` >= NOW()
ORDER BY `WorkshopUserSessions`.`begindate` ASC
")) {
Any help would greatly be aprreciated!
Thanks,
Cam
I think you need to modify it like this
enddate + INTERVAL 1 DAY >= NOW()
Ofcourse this adds 24 hours, for 23:59:59 just change >= to >
It sounds like you just need to use date_add
DATE_ADD(`WorkshopUserSessions`.`enddate`, INTERVAL 1 DAY) > NOW()
Try replacing:
AND `WorkshopUserSessions`.`enddate` >= NOW()
with
AND DATE(`WorkshopUserSessions`.`enddate`) = CURDATE()
Hope it helps.

How to minimize the load in queries that need grouping with different invervals?

I'm looking for a best practice advice how to speed up queries and at the same time to minimize the overhead needed to invoke date/mktime functions. To trivialize the problem I'm dealing with the following table layout:
CREATE TABLE my_table(
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
important_data INTEGER,
date INTEGER);
The user can choose to show 1) all entries between two dates:
SELECT * FROM my_table
WHERE date >= ? AND date <= ?
ORDER BY date DESC;
Output:
10-21-2009 12:12:12, 10002
10-21-2009 14:12:12, 15002
10-22-2009 14:05:01, 20030
10-23-2009 15:23:35, 300
....
I don't think there is much to improve in this case.
2) Summarize/group the output by day, week, month, year:
SELECT COUNT(*) AS count, SUM(important_data) AS important_data
FROM my_table
WHERE date >= ? AND date <= ?
ORDER BY date DESC;
Example output by month:
10-2009, 100002
11-2009, 200030
12-2009, 3000
01-2010, 0 /* <- very important to show empty dates, with no entries in the table! */
....
To accomplish option 2) I'm currently running a very costly for-loop with mktime/date like the following:
for(...){ /* example for group by day */
$span_from = (int)mktime(0, 0, 0, date("m", $time_min), date("d", $time_min)+$i, date("Y", $time_min));
$span_to = (int)mktime(0, 0, 0, date("m", $time_min), date("d", $time_min)+$i+1, date("Y", $time_min));
$query = "..";
$output = date("m-d-y", ..);
}
What are my ideas so far? Add additional/ redundant columns (INTEGER) for day (20091212), month (200912), week (200942) and year (2009). This way I can get rid of all the unnecessary queries in the for loop. However I'm still facing the problem to very fastly calculate all dates that doesn't have any equivalent in database. One way to simply move the problem could be to let MySQL do the job and simply use one big query (calculate all the dates/use MySQL date functions) with a left join (the data). Would it be wise to let MySQL take the extra load? Anyway I'm reluctant to use all these mktime/date in the for loop. Since I have complete control over the table layout and code even suggestions with major changes are welcome!
Update
Thanks to Greg I came up with the following SQL query. However it still bugs me to use 50 lines of sql statements - build up with php - that maybe could be done faster and more elegantly otherwise:
SELECT * FROM (
SELECT DATE_ADD('2009-01-30', INTERVAL 0 DAY) AS day UNION ALL
SELECT DATE_ADD('2009-01-30', INTERVAL 1 DAY) AS day UNION ALL
SELECT DATE_ADD('2009-01-30', INTERVAL 2 DAY) AS day UNION ALL
SELECT DATE_ADD('2009-01-30', INTERVAL 3 DAY) AS day UNION ALL
......
SELECT DATE_ADD('2009-01-30', INTERVAL 50 DAY) AS day ) AS dates
LEFT JOIN (
SELECT DATE_FORMAT(date, '%Y-%m-%d') AS date, SUM(data) AS data
FROM test
GROUP BY date
) AS results
ON DATE_FORMAT(dates.day, '%Y-%m-%d') = results.date;
You definitely shouldn't be doing a query inside a loop.
You can group like this:
SELECT COUNT(*) AS count, SUM(important_data) AS important_data, DATE_FORMAT('%Y-%m', date) AS month
FROM my_table
WHERE date BETWEEN ? AND ? -- This should be the min and max of the whole range
GROUP BY DATE_FORMAT('%Y-%m', date)
ORDER BY date DESC;
Then pull these into an array keyed by date and loop over your data range as you are doing (that loop should be pretty light on CPU).
Another idea is not to use string inside the query. Transform the string parameter to datetime, on mysql.
STR_TO_DATE(str,format)
http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html

Categories