month on month records - mysql

Apologies if my question is structured incorrectly, first time user.
I would like to get all records from the current DateTime and previous month for the same date range e.g. 01st-15th. The date field has a timestamp so would like all the records to the hour and minute.
select
'Total' as 'Measure',
sum(pa.amount) as 'Current Month'
from pay as pa
inner join mem as me on pa.me_id = me.me_id
where pa.pa_completed between last_day(current_date() - interval 1 month) +
interval 1 day
and if(current_date() = current_date(),current_timestamp(),current_date())
group by 1
union all
select
'Total' as 'Measure',
sum(pa.amount) as 'Last Month'
from pay as pa
inner join mem as me on pa.me_id = me.me_id
where pa.pa_completed between last_day(current_date() - interval 2 month) +
interval 1 day
and if(current_date() = current_date(),current_timestamp() - interval 1
month,current_date() - interval 1 month)
group by 1
The where clause in the above codes does not seem to be returning the correct records. I have cross checked the output on both sets of SQL to our admin system and the figures are slightly off.
Is there something I am doing wrong in the code? or is there a better solution to get the output I am after?
I will be using the above code on a dashboard so the current_date() will change everyday.

Related

Counting all rows in column with two different date conditions

I'm trying to turn two count queries with date conditions (the ones below) into one query.
SELECT COUNT(*) as yesterday FROM orders WHERE DATE(timedate) = DATE(NOW() - INTERVAL 1 DAY)
SELECT COUNT(*) as yesterday FROM orders WHERE DATE(timedate) = DATE(NOW() - INTERVAL 2 DAY)
Following the advice of another answer I created the following, but that doesn't seem to work syntax-wise, and I'm not quite sure why. Is there another way to do this? I can't find a similar question on this
SELECT
SUM(IF(DATE(timedate) = DATE(NOW() - INTERVAL 1 DAY))) AS testcount1,
SUM(IF(DATE(timedate) = DATE(NOW() - INTERVAL 2 DAY))) AS testcount2
FROM
orders
You're missing the output values for the IF expression. Also you should use CURRENT_DATE() so you don't need to convert to a DATE:
SELECT
SUM(IF(DATE(timedate) = CURRENT_DATE() - INTERVAL 1 DAY, 1, 0)) AS testcount1,
SUM(IF(DATE(timedate) = CURRENT_DATE() - INTERVAL 2 DAY, 1, 0)) AS testcount2
FROM
orders
Note that MySQL treats boolean expressions as 1 (true) or 0 (false) in a numeric context, so you can actually SUM the expression without needing the IF:
SELECT
SUM(DATE(timedate) = CURRENT_DATE() - INTERVAL 1 DAY) AS testcount1,
SUM(DATE(timedate) = CURRENT_DATE() - INTERVAL 2 DAY) AS testcount2
FROM
orders
You want conditional aggregation. I would phrase the query as follows:
SELECT
SUM(
timedate >= CURRENT_DATE - INTERVAL 1 DAY
and timedate < CURRENT_DATE
) AS testcount1,
SUM(
timedate >= CURRENT_DATE - INTERVAL 2 DAY
and timedate < CURRENT_DATE- INTERVAL 1 DAT
) AS testcount2
FROM orders
Details:
this uses a nice feature of MySQL, that evaluates false/true conditions as 0/1 in numeric context
no date functions are applied on the timedate column : instead, we do litteral date comparisons. This is much more efficient, since the database can possibly take advantage of an index on the datetime column
You might also want to add a WHERE clause to the query:
WHERE
timedate >= CURRENT_DATE - INTERVAL 2 day
AND timedate< CURRENT_DATE

How to count new users in last month in SQL?

I want to know how many new users we have last month, and how many of them have turned into buyers while I can not figure it out smoothly.the following is what I coded.
SELECT COUNT(DISTINCT(PRODUCT_ID))
FROM ORDER_TABLE AS O
INNER JOIN CUSTOMER_TABLE AS C
ON O.CUSTOMER_ID=C.CUSTOMER_ID
WHERE DATEDIFF(MONTH,ORDER_DATE,GETDATE())<=1
And there is another question which has confused me a lot: Which category have the highest YEAR BY YEAR growth in terms of revenue in 2016?
This should do it...
SELECT COUNT(Customer_ID)
FROM Customer_Table
WHERE Customer_ID IN (
SELECT Customer_ID
FROM Order_Table
)
AND DATEDIFF(MONTH, First_Visit, GETDATE()) <= 1
Guessing ...
This gives a list of the new users last month.
SELECT Customer_ID, Country, Gender
FROM Customer_Table
WHERE First_Visit >= (LAST_DAY(CURDATE()) + INTERVAL 1 DAY) - INTERVAL 2 MONTH
AND First_Visit < (LAST_DAY(CURDATE()) + INTERVAL 1 DAY) - INTERVAL 1 MONTH
That date range, given that today is 2017-08-14, looks like this after all the date arithmetic. That means "the calendar month immediately preceding this day."
WHERE First_Visit >= '2017-07-01'
AND First_Visit < '2017-08-01'
The Number of new visitors last month is a simple summary of that query.
SELECT COUNT(*)
FROM Customer_Table
WHERE First_Visit >= (LAST_DAY(CURDATE()) + INTERVAL 1 DAY) - INTERVAL 2 MONTH
AND First_Visit < (LAST_DAY(CURDATE()) + INTERVAL 1 DAY) - INTERVAL 1
Now, to elaborate a bit. How do we tell if a new user has purchased anything? We look in the order table. Something like this will do it.
SELECT C.Customer_ID, SUM(O.Order_Amount) Total_Order_Amount
FROM Customer_Table C
LEFT JOIN Order_Table O ON C.Customer_ID = O.Customeer_ID
WHERE First_Visit >= (LAST_DAY(CURDATE()) + INTERVAL 1 DAY) - INTERVAL 2 MONTH
AND First_Visit < (LAST_DAY(CURDATE()) + INTERVAL 1 DAY) - INTERVAL 1 MONTH
GROUP BY C.Customer_ID
This gives you a list of new customers, with a column showing how much each has ordered. So a NULL or 0 in the Total_Order_Amount column means a new customer who has never ordered anything.
Pro tip:
Incomplete and vague requirements are definitely part of stupid professor tricks. But they are also part of the world of information technology. Often a big part of a assignment, or a contract, or a project, is taking ridiculously vague requirements like the ones you've been given and refining them into something useful.

Introducing a new column for previous month sum

I am trying to introduce a new column for my query, it currently counts sum of expenses in this month, the new column should display last months expences. I am not quite sure where to place it.
SELECT cat.id_kat,
cat.nazwa,
coalesce(exp.tot, 0) AS PriceTotal
FROM wydatki_kategorie cat
LEFT JOIN
(SELECT wydatki_wpisy.kategoria,
sum(wydatki_wpisy.brutto) AS tot
FROM wydatki_wpisy
LEFT JOIN wydatki ON wydatki_wpisy.do_wydatku = wydatki.id_wydatku
WHERE MONTH(wydatki.data_zakupu) = MONTH(CURRENT_DATE())
AND wydatki.id_kupujacy = 1
GROUP BY wydatki_wpisy.kategoria) exp ON cat.id_kat = exp.kategoria
Possibly might be needed ( if I'm not wrong ) - Where clause for the previous month.
wydatki.data_zakupu >= DATE_ADD(LAST_DAY(DATE_SUB(NOW(), INTERVAL 2 MONTH)), INTERVAL 1 DAY) AND
wydatki.data_zakupu<= DATE_SUB(NOW(), INTERVAL 1 MONTH)
SQL Fiddle example
Two things.
First, if you stop using WHERE MONTH(wydatki.data_zakupu) = MONTH(CURRENT_DATE()) to choose your dates you'll get three benefits.
Your date searching will become sargable: an index will speed it up.
You'll get a more general scheme for choosing months.
If you have multiple years' worth of data in your tables, things will work better.
Instead, in general use this sort of expression to search for the present month. You already figured out most of this.
WHERE wydatki.data_zakupu >= LAST_DAY(CURRENT_DATE()) + INTERVAL 1 DAY - INTERVAL 1 MONTH
AND wydatki.data_zakupu < LAST_DAY(CURRENT_DATE()) + INTERVAL 1 DAY - INTERVAL 0 MONTH
This looks for all datetime values on or after midnight at the first day of the present month, and before, but not on <, midnight at the first day of next month.
It generalizes to any month you want. For example,
WHERE wydatki.data_zakupu >= LAST_DAY(CURRENT_DATE()) + INTERVAL 1 DAY - INTERVAL 2 MONTH
AND wydatki.data_zakupu < LAST_DAY(CURRENT_DATE()) + INTERVAL 1 DAY - INTERVAL 1 MONTH
gets you last month. This also works when the current month is January, and it works when you have multiple years' worth of data in your tables.
These expressions are a little verbose because MySQL doesn't have a FIRST_DAY(date) function, only a LAST_DAY(date) function. So we need all that + INTERVAL 1 DAY monkey business.
Second, pulling out a previous month's data is as simple as adding another LEFT JOIN ( SELECT... clause to your table, like so. (http://sqlfiddle.com/#!9/676df4/13)
SELECT ...
coalesce(month1.tot, 0) AS LastMonth
FROM wydatki_kategorie cat
LEFT JOIN
...
LEFT JOIN
(SELECT wydatki_wpisy.kategoria,
sum(wydatki_wpisy.brutto) AS tot
FROM wydatki_wpisy
LEFT JOIN wydatki ON wydatki_wpisy.do_wydatku = wydatki.id_wydatku
WHERE wydatki.data_zakupu >= LAST_DAY(CURRENT_DATE()) + INTERVAL 1 DAY - INTERVAL 2 MONTH
AND wydatki.data_zakupu < LAST_DAY(CURRENT_DATE()) + INTERVAL 1 DAY - INTERVAL 1 MONTH
AND wydatki.id_kupujacy = 1
GROUP BY wydatki_wpisy.kategoria
) month1 ON cat.id_kat = month1.kategoria
As you can see, the date range WHERE clause here gets the previous month's rows.

MySQL Query to get all rows for 2 months ago

I need to do a select where I can chose to see results for current month, previous month, 1 month ago, 2 months ago, 3 months ago.
I found this question: MySQL: Query to get all rows from previous month, but I'm stuck with a filter that will get me all the results for 2 months ago from first to last day of the month.
I tried with this but it doesn't work:
SELECT * FROM table
AND MONTH(date_created) = MONTH(1 MONTH - INTERVAL 2 MONTH);
Try this:
SELECT * FROM table
WHERE MONTH(date_created) = MONTH(NOW() - INTERVAL 2 MONTH)
AND (
YEAR(date_created) = YEAR(NOW())
OR
YEAR(date_created) = YEAR(NOW() - INTERVAL 2 MONTH)
);
Returning records CREATED PRIOR the last 2 months only in MySQL.
If you want all rows from 2 months ago, then use logic like this:
WHERE date_created >= DATE_SUB(DATE_SUB(CURDATE(), 1 - DAY(CURDATE())), INTERVAL 2 MONTH) AND
date_created < DATE_SUB(DATE_SUB(CURDATE(), 1 - DAY(CURDATE())), INTERVAL 1 MONTH)
What is this doing? First, it is only applying functions to the current date part of the expression. This allows MySQL to use an index on date_created, if available and appropriate.
The expression DATE_SUB(CURDATE(), 1 - DAY(CURDATE()) is simply a way to get the first day of the month.
You query have an error, correct one would be:
SELECT * FROM table
WHERE MONTH(date_created) = MONTH(DATE_SUB(NOW(),INTERVAL 2 MONTH))
For current month just MONTH(NOW()), replace "2" with any number of months you need (1,3,.. 23)
as mentioned in comments this solution ignores YEAR differences, it just selects all records with the same month, no matter the year
you can filter wrong year results with additional clause:
AND YEAR(date_created) = '2019' # or year you need
Or use more complex query:
SELECT * FROM table
where
date_created between
/* first day of -2 month*/
date_sub(date_sub(now(),interval 2 month), interval (day(now())-1) day)
and
/* last day of -2 month*/
last_day(date_sub(now(),interval 2 month))

How to decrease SQL Query from last 30 days until now?

I am trying to get the amount of data for the last 30 days.
SELECT ( Now() - interval 1 month ),
Count(flightid) AS count
FROM flight
WHERE flightstatus = 0
AND flightvisibility = 1
AND flightvaliddate > Now()
AND flightvaliddate >= ( Now() - interval 1 month )
Right now this is working ok and it's giving me only 1 row that corresponds to the same day of last month.
What I would like is to get the remaining data from each day until now. How can I do this?
I am using MySQL.
The condition in the WHERE clause is wrong.
And since you want day wise data of last thirty days till now then you must have to use GROUP BY.
SELECT
DATE(flightvalidate) AS flightValidateDate,
Count(flightid) AS count
FROM
flight
WHERE
flightstatus = 0
AND flightvisibility = 1
AND DATE(flightvaliddate) >= CURDATE() - INTERVAL 1 MONTH
GROUP BY flightValidateDate
ORDER BY flightvalidate