Anyway to make Union statements smaller? - mysql

Is there anyway I can make this statement smaller? for efficiency, the whole idea is to get
todays, this month and last months amount of "quotes".
SELECT COUNT(QuoteDate) AS today
FROM database
WHERE QuoteDate >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)
UNION
SELECT COUNT(QuoteDate) AS this_month
FROM database
WHERE QuoteDate >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH)
UNION
SELECT COUNT(QuoteDate) AS last_month
FROM database
WHERE QuoteDate >= DATE_SUB(CURRENT_DATE(), INTERVAL 2 MONTH)
Thanks

Couldn't you just use an OR statement?
SELECT COUNT(QuoteDate) AS today FROM database
WHERE
QuoteDate >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)
OR
QuoteDate >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH)
OR
QuoteDate >= DATE_SUB(CURRENT_DATE(), INTERVAL 2 MONTH)

Untested:
SELECT
sum(if(quotedate >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY), 1, 0)) AS today,
sum(if(quotedate >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), 1, 0)) AS this_month,
sum(if(quotedate <= DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), 1, 0)) AS last_month
FROM database
WHERE QuoteDate >= DATE_SUB(CURRENT_DATE(), INTERVAL 2 MONTH)
The idea is to move the selection made in the where clause to the field clause and do the calculation there.
Note, that the third clause is reversed, as you might only want those entries which are older than 1 month.

Related

SQL turnover of the day before last year

I'm blocking on an SQL query. I am looking to recover the turnover of last year but the day before. For example: we are the 13/08/19 and I wish the turnover of yesterday of last year so 12/08/18.
How can I do that? Here is my request:
SELECT SUM(total_paid/1.2)
FROM '._DB_PREFIX_.'orders
WHERE o.date_add BETWEEN DATE_FORMAT(
CASE
WHEN YEAR( DATE_SUB( now(), INTERVAL 364 DAY ) ) = YEAR(now() )
THEN DATE_SUB(concat(YEAR(now()),'-',MONTH(now()),'-01'), INTERVAL 371 DAY)
ELSE DATE_SUB(concat(YEAR(now()),'-',MONTH(now()),'-01'), INTERVAL 364 DAY) END, '%Y/%m/%d') AND
CASE
WHEN YEAR( DATE_SUB( now(), INTERVAL 364 DAY ) ) = YEAR(now() )
THEN DATE_SUB(now(), INTERVAL 371 DAY)
ELSE DATE_SUB(now(), INTERVAL 364 DAY) END
AND valid=1
table
Thanks for help.
It seems you should be able to simplify your query to something like this:
SELECT SUM(total_paid/1.2)
FROM '._DB_PREFIX_.'orders
WHERE DATE(o.date_add) = CURDATE() - INTERVAL 1 YEAR - INTERVAL 1 DAY
Note that dependent on how you want to treat February 29, you may want to change the expression to
CURDATE() - INTERVAL 1 DAY - INTERVAL 1 YEAR
In the first form, 2020-02-29 will map to 2019-02-27, in the second it will map to 2019-02-28.
{
select sum(your_total_column/1.2) from your_tab
where now() =(CASE WHEN mod(year(your_date_column),4) = 0
THEN DATE_ADD(your_date_column,INTERVAL 367 DAY)
ELSE DATE_ADD(your_date_column,INTERVAL 366 DAY));}
The idea is find if your_date_column is leap year if it is leap year then add 367 else add 366 and compare with current date.

DATE_ADD(LAST_DAY(DATE_SUB(NOW(), INTERVAL 2 MONTH)), INTERVAL 1 DAY)

DATE_ADD(LAST_DAY(DATE_SUB(NOW(), INTERVAL 2 MONTH)), INTERVAL 1 DAY)- I have this in mySQL, and I'm taking it into BigQuery. BigQuery does not have Last_Day function.
This getting the first of the month by calculating the last_day of the month before and adding one day.
Below is for BigQuery Standard SQL
#standardSQL
SELECT DATE_SUB(DATE_SUB(DATE_TRUNC(CURRENT_DATE(), MONTH), INTERVAL 1 MONTH), INTERVAL 1 DAY)
if you run it today (2019-04-25) the output is
Row f0_
1 2019-02-28
Not sure what exactly you your target - I think below option is better represent your mysql version
#standardSQL
SELECT DATE_SUB(DATE_TRUNC(CURRENT_DATE(), MONTH), INTERVAL 1 MONTH)
with result
Row f0_
1 2019-03-01
You could use DATE_FORMAT(date ,'%Y-%m-01')
DATE_ADD( DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 2 MONTH) ,'%Y-%m-01'), INTERVAL 1 DAY)

How do I retrieve data for the previous month in SQL

I want to get data for the dates between 2015-05-01 and 2015-06-01 using SQL.
Please help me with the query.
The query I used is:
select *,count(id) as multiple_visitors
from table1
where id=123
and (date(server_time) between (CURDATE() - INTERVAL 31 DAY) AND CURDATE())
group by user_id having count(id)>1
You can do this with month() and year():
where month(server_time) = month(curdate() - interval 1 month) and
year(server_time) = year(curdate() - interval 1 month)
However, I recommend a slightly more complex expression:
where server_time >= date_sub(date_sub(curdate(), interval - day(curdate()) + 1 day), interval 1 month) and
server_time < date_sub(curdate(), interval - day(curdate()) + 1 day)
The advantage is that there are no functions on server_time, so the database engine can use an index, if appropriate.
As a note: the expression date_sub(curdate(), interval - day(curdate()) + 1 day) gets midnight on the first day of the month.
Try using "WHERE" with MONTH(date).
Like this:
SELECT * FROM Table
WHERE MONTH(date) = 1

Retrieving Data from database on quaterly basis condition But it should be based on current year data only

I had tried this code:
Its works also fine,but the issue is, if current month is feb and fire this query then it considers past 3 months from now and hence starts from past year i.e 2012 nov or dec say i want only current year data,if it is feb now and i fire this query then it should only show jan and feb records.
SELECT CROEmailId,
(
SELECT COUNT(LeadId)
FROM LeadStatus
WHERE DATE(`LeadTime`)> DATE_SUB(now(),
INTERVAL 3 MONTH
)
AND Generated=1 and AssignedTo=a.CROEmailId)
AS 'NEW LEAD',(
SELECT COUNT(LeadId)
FROM LeadHistory
WHERE DATE(UpdatedAt)> DATE_SUB(now(),
INTERVAL 3 MONTH
) AND AssignedTo=a.CROEmailId)
AS 'Lead Updated',
(
SELECT SUM(TotalEmails)
FROM MailJobs
WHERE DATE(CompletedAt)> DATE_SUB(now(),
INTERVAL 3 MONTH
)
AND MailFrom=a.CROEmailId)
AS 'Email Uploaded',
(
SELECT SUM(TotalSent)
FROM MailJobs
WHERE DATE(CompletedAt)> DATE_SUB(now(),
INTERVAL 3 MONTH)
AND MailFrom=a.CROEmailId
)
AS 'Email Sent',
(
SELECT SUM(NetTotal)
FROM Invoice
WHERE Status='PAID'
AND DATE(CreatedAt)> DATE_SUB(now(), INTERVAL 3 MONTH)
AND CROEmailId=a.CROEmailId)
AS 'Payment Today' FROM CustomersManager a;
Try change
DATE_SUB(now(), INTERVAL 3 MONTH)
to
IF(MONTH(CURDATE()) < 4, DATE_FORMAT(CURDATE(), '%Y-01-01'), CURDATE() - INTERVAL 3 MONTH)
in all subqueries.
SELECT CROEmailId,
(SELECT COUNT(LeadId)
FROM LeadStatus
WHERE DATE(`LeadTime`)> IF(MONTH(CURDATE()) < 4, DATE_FORMAT(CURDATE(), '%Y-01-01'), CURDATE() - INTERVAL 3 MONTH)
AND Generated=1
AND AssignedTo=a.CROEmailId) AS 'NEW LEAD',
(SELECT COUNT(LeadId)
FROM LeadHistory
WHERE DATE(UpdatedAt)> IF(MONTH(CURDATE()) < 4, DATE_FORMAT(CURDATE(), '%Y-01-01'), CURDATE() - INTERVAL 3 MONTH)
AND AssignedTo=a.CROEmailId) AS 'Lead Updated',
(SELECT SUM(TotalEmails)
from MailJobs
WHERE DATE(CompletedAt)> IF(MONTH(CURDATE()) < 4, DATE_FORMAT(CURDATE(), '%Y-01-01'), CURDATE() - INTERVAL 3 MONTH)
AND MailFrom=a.CROEmailId) AS 'Email Uploaded',
(SELECT SUM(TotalSent)
FROM MailJobs
WHERE DATE(CompletedAt)> IF(MONTH(CURDATE()) < 4, DATE_FORMAT(CURDATE(), '%Y-01-01'), CURDATE() - INTERVAL 3 MONTH)
AND MailFrom=a.CROEmailId) AS 'Email Sent',
(SELECT SUM(NetTotal)
FROM Invoice
WHERE Status='PAID'
AND DATE(CreatedAt)> IF(MONTH(CURDATE()) < 4, DATE_FORMAT(CURDATE(), '%Y-01-01'), CURDATE() - INTERVAL 3 MONTH)
AND CROEmailId=a.CROEmailId) AS 'Payment Today'
FROM CustomersManager a;
use this in your query to find record filter by year
YEAR( '20013-12-12' )
example,
SELECT * FROM TABLE WHERE YEAR(DATE_FIELD) = 2013

Using a variable/function as a dynamic column name in MySQL

Is it possible to use a function or a variable as the label for a column in MySQL?
So for example if you wanted to include the date, something like:
select
sum(P.AMOUNT) AS monthname(date_sub(CURDATE(), INTERVAL 1 MONTH))
from
PAYMENT P
WHERE
P.CREATED_DATE > (date_sub(CURDATE(), INTERVAL 1 MONTH));
This fails, as it's not the correct syntax for an AS alias. I've also tried this:
SET #s = monthname(date_sub(CURDATE(), INTERVAL 1 MONTH));
select
sum(P.AMOUNT) AS #s
from
PAYMENT P
WHERE
P.CREATED_DATE > (date_sub(CURDATE(), INTERVAL 1 MONTH));
Which also doesn't work...
Any ideas?
EDIT - With the above example i realize you could actually just use an additional column to return the date info. The problem is i have a few columns with various date ranges, like this:
select
sum(IF((P.CREATED_DATE BETWEEN DATE_SUB(CURDATE(), INTERVAL 1 MONTH) and DATE_SUB(CURDATE(), INTERVAL 0 MONTH)),P.amount,0)) AS 'Month 0',
sum(IF((P.CREATED_DATE BETWEEN DATE_SUB(CURDATE(), INTERVAL 2 MONTH) and DATE_SUB(CURDATE(), INTERVAL 1 MONTH)),P.amount,0)) AS 'Month -1',
sum(IF((P.CREATED_DATE BETWEEN DATE_SUB(CURDATE(), INTERVAL 3 MONTH) and DATE_SUB(CURDATE(), INTERVAL 2 MONTH)),P.amount,0)) AS 'Month -2'
from
PAYMENT P
WHERE
P.AMOUNT < 100000;
So it's the "Month 0" etc i'm looking to replace with a function/query.