update database sum monthly based on signup date - php

Need help writing a function for database. I want to keep track of the total cost of member orders each month based on their signup date. So if someone signed up in the middle of the month, the function should add 30 days to their signup date and sum the sales whithin that period and place in database. Then display on user page. Using mysql functions (not PDO or mysqli for now).
Something like:
<?php
$query = ("SELECT SUM(cost) FROM memberOrders WHERE
memberNumber='$memberNumber' GROUP BY signupdate+30days");
?>
But it can't be just 30 days...it should be +30, +60, +90...That's the part I'm stuck on. Thanks!

calculate the start/end date in PHP and make use of a subquery:
SELECT SUM(cost) FROM
(Select cost, membernumber from memberOrders WHERE
memberNumber='$memberNumber' and date >= '$startdate' and date <= '$enddate'
GROUP BY substr(date, 7))
GRoup by membernumber

Assuming you have both the signup date and order date in MemberOrders, the following will return all months with orders:
SELECT datediff(orderdate, signupdate, interval month) as MonthsAfter,
SUM(cost) as MonthCost
FROM memberOrders
WHERE memberNumber='$memberNumber'
GROUP BY datediff(orderdate, signupdate, interval month)
If you have all months having 30-days, you can do:
SELECT floor(datediff(orderdate, signupdate, interval day)/30) as Months,
SUM(cost) as MonthCost
FROM memberOrders
WHERE memberNumber='$memberNumber'
GROUP BY floor(datediff(orderdate, signupdate, interval day)/30)
Note: both of these assign "0" to the first month after signup. Add +1 if you want to start at 1.

Related

How to count rows called orders from the last 30 days and sum up the price of that order?

The order table is made up of quantity, price, username and orderdate which is in datetime format.
An order is submitted from a cart page, if multiple items are submitted such as 8 monitors and 2 pcs. It will input those as two separate records.
The goal: To multiply the quantity by the price for each record a user has, then to add those records up for the last 30 days.
Tried the below code to get the orders from the last 30 days which isnt working.
edit: working code for getting orders from last 30 days
SELECT * FROM `orders`
where orderdate between adddate(now(),-30) and now()
Honestly not sure where to start with the above sql statement, not sure where exactly the groupbys, count and sum() functions go since I am only starting with sql.
You can use below query
SELECT SUM(`price`) AS sum FROM orders
WHERE `orderdate` BETWEEN DATE_SUB(NOW(), INTERVAL 30 DAY) AND NOW();
If you need to count row and sum the sales price
SELECT SUM(`price`) AS sum,COUNT(*) AS counter FROM orders
WHERE `orderdate` BETWEEN DATE_SUB(NOW(), INTERVAL 30 DAY) AND NOW();
Alternatively, if you wanted these queries by username,
SELECT SUM(`price`) AS sum FROM orders
WHERE uname = 'test' and `orderdate` BETWEEN DATE_SUB(NOW(), INTERVAL 30 DAY) AND NOW();
SELECT SUM(`price`) AS sum,COUNT(*) AS counter FROM orders
where uname = 'test' and `orderdate` BETWEEN DATE_SUB(NOW(), INTERVAL 30 DAY) AND NOW();
Be more explicit:
WHERE orderdate >= CURRENT_TIMESTAMP - INTERVAL 30 DAY
Or, because you probably do not care about the time component:
WHERE orderdate >= CURRENT_DATE - INTERVAL 30 DAY
In order to get the "total order value" for the last 30 days, you need to calculate SUM() on price*quantity:
SELECT SUM(price*quantity) AS total_order_value
FROM orders
WHERE orderdate BETWEEN NOW() - INTERVAL 30 DAY and NOW()

Display payment made by mark every 3 month for the last 3 years

I have a table called payment it has date field, i have a customer called Mark who has been making payment every day for 3 years
Table: Payment
Fields: Name , Amountpaid, date
I want to display payment record made by mark every 3 month and also the total Amountpaid for 3 years
How i want the result to look like
First 3 months payment record table
total Amountpaid at the bottom of the table
second 3 months payment record table
total Amountpaid at the bottom of the table
Third 3 months payment record table
total Amountpaid at the bottom of the table
and so on for 3 years
Please do help out
It seems like you're looking for a SQL solution for this, but databases are for holding data, they aren't for formatting it into a report. To this end my advice would be: Don't try and do this in the database, do it in the front end code instead
It will be very simple to run a query like
SELECT * FROM payment WHERE
name = 'mark' and
`date` between date_sub(now(), interval 3 year) and now()
ORDER BY date
And then put the results into an HTML table usig a loop, and a variable that keeps track of the amount paid total. Every 3 months reset the variable. If you want MySQL to do a bit more data processing to help out you can do this:
SELECT * FROM
payment
INNER JOIN
(SELECT YEAR(`date`) + (QUARTER(`date`)/10) as qd, SUM(amountpaid) as qp FROM payment WHERE name = 'mark' GROUP BY YEAR(`date`), QUARTER(`date`)) qpt
ON
qpt.qd = YEAR(`date`) + (QUARTER(`date`)/10)
WHERE
name = 'mark' AND
`date` between date_sub(now(), interval 3 year) and now()
ORDER BY `date`
This will give all mark's data row by row and an extra two columns (that mostly repeat themselves over and over) showing the year and quarter (3 months) of the year like 2017.1, 2017.2, together with a sum of all payments made in that quarter. Formatting it in the front end now won't need a variable to keep a running total of the amount paid
This is about the limit of what you should do with formatting the data in the database (personal opinion). If, however, you're determined to have MySQL do pretty much all this, read on..
Ysth mentioned rollup, which is intended for summarising data.. such a solution would look like this:
SELECT
Name, `date`, SUM(amountpaid) as amountpaid
FROM
payment
WHERE
name = 'mark' AND
`date` between date_sub(now(), interval 3 year) and now()
GROUP BY
name,
YEAR(`date`) + (QUARTER(`date`)/10),
`date`
WITH ROLLUP
The only downside with this approach is you also get a totals row for all payments by mark. To suppress that, use grouping sets instead:
SELECT
Name, `date`, SUM(amountpaid) as amountpaid
FROM
payment
WHERE
name = 'mark' AND
`date` between date_sub(now(), interval 3 year) and now()
GROUP BY GROUPING SETS
(
(
name,
YEAR(`date`) + (QUARTER(`date`)/10),
`date`
),
(
name,
YEAR(`date`) + (QUARTER(`date`)/10)
)
)
You can use a group by on the year and month divided by 3 and truncated using floor
SELECT
EXTRACT(YEAR_MONTH FROM `date`),
SUM(`Amountpaid`)
FROM
`Payment`
WHERE
`Name` = 'Mark'
AND `date` >= DATE_SUB(NOW(), INTERVAL 3 YEAR)
GROUP BY
EXTRACT(YEAR FROM `date`),
FLOOR(EXTRACT(MONTH FROM `date`) / 3)
For the total you will need to iterate the result set and sum up the amounts paid, or if you want it as the final record you could do a UNION SELECT but this would be ineffecient, but for completeness it is below:
SELECT
EXTRACT(YEAR_MONTH FROM `date`),
SUM(`Amountpaid`)
FROM
`Payment`
WHERE
`Name` = 'Mark'
AND `date` >= DATE_SUB(NOW(), INTERVAL 3 YEAR)
GROUP BY
EXTRACT(YEAR FROM `date`),
FLOOR(EXTRACT(MONTH FROM `date`) / 3)
UNION SELECT
NULL,
SUM(`Amountpaid`)
FROM
`Payment`
WHERE
`Name` = 'Mark'
AND `date` >= DATE_SUB(NOW(), INTERVAL 3 YEAR)
This is for get summary per 3 months :
select year(date)*100+floor(month(date)/3) as period, sum(amountpaid)
from payment
where name = 'mark' and (date between '2014-01-01' and '2017-01-01')
group by year(date)*100+floor(month(date)/3)
order by period
And this is how to get summary 3 year :
select sum(amountpaid) from payment where name = 'mark' and (date between '2014-01-01' and '2017-01-01')
You can change the date between for your need

{date} function help. Fetch record from mysql of specific dates

I need a help. This code help us when we put specific dates in box.
But if we want records of last 10days then what should we need to do.
Automatic records of last 10 days
$sql = "select * from pub_website where user='$user' && STR_TO_DATE(pdate,'%Y-%m-%d') = '$fromdate' && website='$site'";
To select all records within a certain date range:
SELECT * FROM pub_website WHERE pdate BETWEEN "2015-12-01 00:00:00" AND NOW()
To do this dynamically, so to speak, for the last 10 days:
SELECT * FROM pub_website WHERE pdate BETWEEN DATE_SUB(NOW(), INTERVAL 10 DAY) AND NOW();

MySQLi "CURRENT_MONTH_BEGINNING"... is there a way to get that?

I am interested in collecting data from the last month in the database with MySQLi.
But using INTERVAL 1 MONTH each month overlaps the other, so is there a way to tell the function to check my current month, start from the first day, and collect all data from said month?
Something like:
SELECT count(DISTINCT ip) AS visitor_ip FROM visitor_list
WHERE visited_date > ( INTERVAL CURRENT_MONTH_BEGINNING)
You can just use the current year and month, and 01 as the day:
SELECT count(DISTINCT ip) AS visitor_ip
FROM visitor_list
WHERE visited_date > CONCAT(DATE_FORMAT(NOW(),'%Y%m'), '01')
This has the advantage that any index on visited_date will still be used correctly.
First you need to generate current month starting date from PHP like this:
$monthStartDate = date('Y-m').'-01';
Then your query will become:
$sql = "SELECT count(DISTINCT ip) AS visitor_ip FROM visitor_list WHERE visited_date > DATE_SUB(now(), interval (datediff(now(), '".$monthStartDate."')) day)";

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()) );

Categories