I have a table with this data :
id quantity month year
1 10 12 2020
2 78 3 2019
3 67 4 2020
4 78 3 2020
5 56 2 2020
6 34 4 2017
7 56 2 2017
I want to get all data's from 2017, month 3 till 2020 month 3
My sql look like :
where (dc.year >= 2017 and dc.month >= 3) and (dc.year <= 2020 and dc.month <= 3)
GROUP BY dc.year, dc.month
this sql get only data for 2017,3 and 2018, 3 and 2019,3 and 2020,3
But I need the whole interval. If I put
where dc.year >= 2017 and dc.year <= 2020
GROUP BY dc.year, dc.month
Getting all datas but I need data from 2017 month 3 -----> 2020 month 3 (all interval)
One method uses arithmetic:
where dc.year * 12 + dc.month between 2017 * 12 + 3 and 2020 * 12 + 3
Alternative, you can use a more complex expression:
where (dc.year = 2017 and dc.month >= 3) or
(dc.year > 2017 and dc.year < 2020) or
(dc.year = 202 and dc.month <= 3)
You could simply build dates from these numbers and use them for comparison. I think that it makes the intent clearer, and really is in the spirit of your logic (which is to filter by date):
In SQL Server:
where datefromparts(year, month, 1) between '2017-03-01' and '2020-03-01'
In MySQL:
where concat_ws('-', year, month, 1) between '2017-03-01' and '2020-03-01'
Related
I have sample dates in a table and what I need to get is each of the months between the start date and end date.
sample :
ID Startdate EndDate
1 01-01-2019 01-03-2019
2 01-08-2019 01-02-2020
I need to fetch months and year from these dates.
Desired output :
ID Dates
1 January 2019
1 February 2019
1 March 2019
2 August 2019
2 September 2019
2 October 2019
2 November 2019
2 December 2019
2 January 2020
2 February 2020
How cah I achieve this in MySQL and how to do increment or any loop kind of operation. On the query side I'm not getting any idea to move on this.
Here are a couple of ways to achieve this. The first will only work on MySQL 8+ and uses a recursive CTE to generate the months between StartDate and EndDate:
WITH RECURSIVE CTE AS (
SELECT ID, Startdate AS d, EndDate
FROM dates
UNION ALL
SELECT ID, d + INTERVAL 1 MONTH, EndDate
FROM CTE
WHERE d < EndDate
)
SELECT ID, DATE_FORMAT(d, '%M %Y') AS Dates
FROM CTE
ORDER BY ID, d
The second (which will run on any version of MySQL) uses a numbers table (in this case numbers from 0 to 99, allowing for a range of up to 99 months between StartDate and EndDate; if you need longer, adding more tables to the CROSS JOIN will increase that range by a factor of 10 for each table added) to generate the list of months difference, this is then JOINed to the original table so that the generated date Startdate + INTERVAL n.n MONTH is less than or equal to EndDate:
SELECT ID, DATE_FORMAT(Startdate + INTERVAL n.n MONTH, '%M %Y') AS Dates
FROM dates
JOIN (
SELECT n10.n * 10 + n1.n * 1 AS n
FROM (
SELECT 0 n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) n10
CROSS JOIN (
SELECT 0 n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) n1
) n ON Startdate + INTERVAL n.n MONTH <= EndDate
ORDER BY ID, Startdate + INTERVAL n.n MONTH
Having generated our list of dates, we format it using DATE_FORMAT and a format string of %M %Y. For both queries the output is:
ID Dates
1 January 2019
1 February 2019
1 March 2019
2 August 2019
2 September 2019
2 October 2019
2 November 2019
2 December 2019
2 January 2020
2 February 2020
Demo on dbfiddle
I have a payments table, Where I update the subscription renewal date and amount, now I have a query to select previous 13 months sum of amounts column, But how do I add zero if no payment data is available for any month in the selected last 13 months of record.
SELECT DATE_FORMAT(dtSubscriptionRenewalDate, "%b - %Y") AS month, SUM(intPaymentAmount) as usd13mon FROM `tbl_pi_payment` WHERE strCurrencyCode = 'USD' and dtSubscriptionRenewalDate <= NOW() and dtSubscriptionRenewalDate >= Date_add(Now(),interval - 13 month) GROUP BY DATE_FORMAT(dtSubscriptionRenewalDate, "%Y-%m")
month usd13mon
Oct - 2018 55
Dec - 2018 79
Jan - 2019 16
Feb - 2019 93
Mar - 2019 80
Apr - 2019 83
May - 2019 34
Jun - 2019 23
Jul - 2019 25
Aug - 2019 37
Sep - 2019 17
Oct - 2019 44
In the above-mentioned output the nov 2018 month is missing as there was data available in the table.
You may try introducing a calendar table which represents every month which you want to appear in your report:
SELECT
m.my,
COALESCE(SUM(t.intPaymentAmount), 0) AS usd13mon
FROM
(
SELECT 'Nov - 2018' AS my UNION ALL
SELECT 'Dec - 2018' UNION ALL
SELECT 'Jan - 2019' UNION ALL
...
SELECT 'Nov - 2019'
) m
LEFT JOIN tbl_pi_payment t
ON m.my = DATE_FORMAT(t.dtSubscriptionRenewalDate, '%b - %Y') AND
t.strCurrencyCode = 'USD' AND
t.dtSubscriptionRenewalDate BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL - 13 MONTH)
GROUP BY
m.my;
I am trying to pull a count of data from a database between two dates by using a stored procedure using the below code:
select count(*)
from SOMT_Development.Board_Metrics_Data bmd
where bmd.Metric_Year >= startYear and bmd.Metric_Year <= endYear and
Metric_Month >= startMonth and Metric_Month <= endMonth and
bmd.Metric_Day >= startDay and bmd.Metric_Day <= endDay and
bmd.Board_Metrics_ID = 1 and bmd.Value_Colour = "Red" and
bmd.Date_Created = (select max(bmd2.Date_Created)
from SOMT_Development.Board_Metrics_Data bmd2
where bmd2.Board_Metrics_ID = bmd.Board_Metrics_ID and
bmd2.Metric_Year = bmd.Metric_Year and
bmd2.Metric_Month = bmd.Metric_Month and
bmd2.Metric_Day = bmd.Metric_Day
)) as 'red'
However when the months/years are different it does not work correctly. This is the data that comes back if I input the dates for 2018-3-1 and 2018-4-4
2018-03-29 09:46:20 green 1 no_comment 2018 3 1
2018-03-29 09:46:20 red 1 no_comment 2018 3 2
2018-03-29 09:46:20 white 1 no_comment 2018 3 3
2018-03-29 09:46:20 white 1 no_comment 2018 3 4
2018-04-04 13:25:19 green 1 no_comment 2018 4 4
2018-04-02 13:25:30 green 1 no_comment 2018 4 2
2018-04-03 13:25:47 green 1 no_comment 2018 4 3
As you can see, the days does not go up to the end of the month, it just goes up to the 4th day.
Thanks
As #niyou said, you will run into problems comparing the parts of a date separately, so you need to put them together into a whole date. So try replacing
bmd.Metric_Year >= startYear and bmd.Metric_Year <= endYear and
Metric_Month >= startMonth and Metric_Month <= endMonth and
bmd.Metric_Day >= startDay and bmd.Metric_Day <= endDay
with
STR_TO_DATE(CONCAT_WS('-', bmd.Metric_Year, bmd.Metric_Month, bmd.Metric_Day), '%Y-%c-%e') >= STR_TO_DATE(CONCAT_WS('-', startYear, startMonth, startDay), '%Y-%c-%e') AND
STR_TO_DATE(CONCAT_WS('-', bmd.Metric_Year, bmd.Metric_Month, bmd.Metric_Day), '%Y-%c-%e') <= STR_TO_DATE(CONCAT_WS('-', endYear, endMonth, endDay), '%Y-%c-%e')
Depending on the format of the values in your database, you may need to change the %Y-%c-%e format string to match, the manual will assist in selecting the right string.
Hi i have a table like below
year | month | otherdata
2015 1
2015 1
2015 3
2015 4
2015 4
2016 1
2016 2
2016 2
here how do i select all data of (year 2015/month 4 to year 2016/month 2)
i tried following query.
select * from `schedule_details` where (`year` >= 2015 and `month` >= 4) and (`year` <= 2016 and `month` >= 2)
but its not working. how do i do this? please help
thanks
Solved the problem
Select *
From schedule_details
Where ( year = 2015 And month >= 4 )
Or ( year > 2015 And year < 2016 )
Or ( year = 2016 And month <= 2 )
is there any other better way?
Can anyone assist in a sql statement I am trying to write? I'm using SSRS r1 (either sql or ssrs solution is fine)
How do I:
show count measure split by month and year
for each of those months, I want to count the previous cumulative 12 months
e.g.
2012 jan: counts feb 2011 - jan 2012
2012 feb: counts mar 2011 - feb 2012
2012 mar: counts apr 2011 - mar 2012
I have started this code but it's incorrect, however it gives you an idea of what I am trying to achieve (this issue is I have to calc month and year from a date)
select
count(a.measure) count
,month(a.StartDate)
,year(a.StartDate)
from
a
where
a.StartDate >= DATEADD(mm,DATEDIFF(mm,0,#datepromt)-12,0) as startdateYrAgo --1st month 1 year ago 01/01/2012
and a.StartDate <= DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#datepromt)+1,0)) as startdateEOM --last day of month 31/01/2013
group by
month(a.StartDate)
,year(a.StartDate)
Here you have an idea for the query, it have to look something like below;
SELECT
periods.year
,periods.month
,measures.cnt
FROM (
SELECT DISTINCT
year = YEAR(StartDate)
, month = MONTH(StartDate)
, month_running = DATEDIFF(mm, 0, StartDate)
FROM a
GROUP BY YEAR(StartDate), MONTH(StartDate), DATEDIFF(mm, 0, StartDate)
) periods
JOIN (
SELECT month_running = DATEDIFF(mm, 0, StartDate), cnt = COUNT(measure)
FROM a
GROUP BY DATEDIFF(mm, 0, StartDate)
) measures
ON measures.month_running BETWEEN periods.month_running - 12 AND periods.month_running - 1