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.
Related
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.
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))
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
i got a MySQL tbl, with some colums, where every 5 min. a new row is inserted with 3 values
1. Auto inc. curent Date Unix timestamp --> date
2. power consumption absolut --> wert01
3. Power Generation absolut --> wert02
To Show this Information in a Graph, for Exampl for weekly power consumption, i need to select the First and the last, which allready Works, but then have to Substract the last from the First and Show only tue result & the day of the werk.
SELECT
(SELECT wert01
FROM sml_splitt
WHERE date >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY
AND date < curdate() - INTERVAL DAYOFWEEK(curdate()) DAY
ORDER BY date DESC LIMIT 1) AS 'last',
(SELECT wert01
FROM sml_splitt
WHERE date >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY
AND date < curdate() - INTERVAL DAYOFWEEK(curdate()) DAY
ORDER BY date LIMIT 1) AS 'lirst
I am searching for some days to find a solution, but with no success.
Hopfuly, you could help me.
If you're happy with your query, then you can do the math by nesting it one more time like this: http://sqlfiddle.com/#!9/515ef/1
select t1.last, t1.first, t1.last - t1.first as result
from (
select (
select wert01
from sml_splitt
where dt >= curdate() - interval dayofweek(curdate()) + 6 day
and dt < curdate() - interval dayofweek(curdate()) day
order by dt desc limit 1
) as 'last',
(
select wert01
from sml_splitt
where dt >= curdate() - interval dayofweek(curdate()) + 6 day
and dt < curdate() - interval dayofweek(curdate()) day
order by dt limit 1
) as 'first'
) t1
;
If you really want to work with this data by week for reporting purposes, let me suggest a couple of views. The first will give you all of your distinct beginning of week dates:
create view v1 as
select date(dt) as week_begins
from sml_splitt
where dayofweek(dt) = 1
group by week_begins
The second view joins the first view with itself to give you a week beginning and week ending range:
create view v2 as
select t1.week_begins, coalesce(t2.week_begins,now()) as week_ends
from v1 t1
left join v1 t2
on t2.week_begins = t1.week_begins + interval 7 day
You can see the results here: http://sqlfiddle.com/#!9/a4d1b3/2. Notice that I'm using now() to get the current date and time if the week hasn't ended yet.
From there you can join your view with your original table and use min() and max() function with grouping to get the starting and ending 'wert' values and do any calculations on them that you like.
Here's an example: http://sqlfiddle.com/#!9/a4d1b3/6
select week_begins, week_ends,
min(wert01) as start_wert01,
max(wert01) as end_wert01,
max(wert01) - min(wert01) as power_consumed,
min(wert02) as start_wert02,
max(wert02) as end_wert02,
max(wert02) - min(wert02) as power_generated,
(max(wert02) - min(wert02)) - (max(wert01) - min(wert01)) as net_generated
from v2
inner join sml_splitt
on sml_splitt.dt >= v2.week_begins
and sml_splitt.dt < v2.week_ends
group by week_begins
I hope that helps.
I'm trying to select all the data from the previous month to all the months in the future .. for example , I'd like to select everything from January till any date available in the future on the database, that goes for any month .. select the previous month till the future months of this year
This is my QUERY, It only starts with February , how can I make it start with the previous month .. current month - 1 is not working
SELECT *
FROM events
WHERE YEAR(event_start_date) = YEAR(CURDATE())
AND MONTH(event_start_date) = MONTH(CURDATE())
use DATE_SUB() to select previous month and >= to select all data in the future:
SELECT *
FROM events
WHERE YEAR(event_start_date) = YEAR(CURDATE())
AND MONTH(event_start_date) >= MONTH(DATE_SUB( CURDATE(), INTERVAL 1 MONTH))
Try:
AND MONTH(event_start_date) = MONTH(DATE_SUB(CURDATE(), INTERVAL 1 MONTHS))
The portion DATE_SUB(CURDATE(), INTERVAL 1 MONTH) will subtract a month from the current date. If you want last month and everything in the future, use:
AND MONTH(event_start_date) >= MONTH(DATE_SUB(CURDATE(), INTERVAL 1 MONTHS))
Notice '>='. Although there is an edge case at january that you'll have to get around. The best way might be like this:
WHERE event_start_date >= DATE_SUB(DATE_SUB(CURDATE(), INTERVAL 1 MONTHS), (DAYOFMONTH(CURDATE)) DAYS)
Which will get you everything from the 1st of last month. No edge cases.
Try this
SELECT *
FROM events
WHERE YEAR(event_start_date) = YEAR(CURDATE())
AND MONTH(event_start_date) >= MONTH(CURDATE() - INTERVAL 1 MONTH);
SELECT *
FROM events
WHERE event_start_date >= '1/'+MONTH(DATE_SUB( CURDATE(), INTERVAL 1 MONTH))+'/'+YEAR(DATE_SUB( CURDATE(), INTERVAL 1 MONTH))
For performance, you'd likely want an index range scan operation on the event_start_date column. That means (obviously), you'd want an index with event_start_date as a leading column.
To get an index range scan, the predicate needs to be on the bare event_start_date column, and NOT a function.
WHERE event_start_date >= some_value
For "some_value" in this case, one possible expression you can use would be:
CAST(DATE_FORMAT(NOW()+INTERVAL -1 MONTH ,'%Y-%m-01') AS DATE)
That takes the current date and time, subtracts one month, and then sets the day and time component to midnight of the first of the month.