How to Determine Values for Missing Months based on Data of Previous Months in T-SQL
I'd start by building a Numbers table holding sequential integers from 1 to a million or so. They come in really handy once you get the hang of it.
For example, here is how to get the 1st of every month in 2008:
select firstOfMonth = dateadd( month, n - 1, '1/1/2008')
from Numbers
where n <= 12;
Now, you can put that together using OUTER APPLY to find the most recent transaction for each date like so:
with Dates as (
select firstOfMonth = dateadd( month, n - 1, '1/1/2008')
from Numbers
where n <= 12
)
select d.firstOfMonth, t.TransactionValue
from Dates d
outer apply (
select top 1 TransactionValue
from Transactions
where TransactionDate <= d.firstOfMonth
order by TransactionDate desc
) t;
This should give you what you're looking for, but you might have to Google around a little to find the best way to create the Numbers table.
Detect if a month is missing and insert them automatically with a select statement (MSSQL)
You need a recursive CTE
to get all the years in the table (and the missing ones if any) and another one to get all the month numbers 1-12.
A CROSS
join of these CTEs will be joined with a LEFT
join to the table and finally filtered so that rows prior to the first year/month and later of the last year/month are left out:
WITH
limits AS (
SELECT MIN(year) min_year, -- min year in the table
MAX(year) max_year, -- max year in the table
MIN(DATEFROMPARTS(year, monthnum, 1)) min_date, -- min date in the table
MAX(DATEFROMPARTS(year, monthnum, 1)) max_date -- max date in the table
FROM tablename
),
years(year) AS ( -- recursive CTE to get all the years of the table (and the missing ones if any)
SELECT min_year FROM limits
UNION ALL
SELECT year + 1
FROM years
WHERE year < (SELECT max_year FROM limits)
),
months(monthnum) AS ( -- recursive CTE to get all the month numbers 1-12
SELECT 1
UNION ALL
SELECT monthnum + 1
FROM months
WHERE monthnum < 12
)
SELECT y.year, m.monthnum,
DATENAME(MONTH, DATEFROMPARTS(y.year, m.monthnum, 1)) month,
COALESCE(value, 0) value
FROM months m CROSS JOIN years y
LEFT JOIN tablename t
ON t.year = y.year AND t.monthnum = m.monthnum
WHERE DATEFROMPARTS(y.year, m.monthnum, 1)
BETWEEN (SELECT min_date FROM limits) AND (SELECT max_date FROM limits)
ORDER BY y.year, m.monthnum
See the demo.
SQL Server query to get the data from previous month if the column value is not present in next month
This answers the original version of the question.
Assuming that month
is stored as a date with the first first day of the month, then a simple method uses recursive CTEs:
with cte as (
select restaurant, num_items, month,
dateadd(month, -1,
coalesce(lead(month) over (partition by restaurant order by month),
max(month) over ()
)
) as end_month
from t
union all
select restaurant, num_items, dateadd(month, 1, month), end_month
from cte
where month < end_month
)
select *
from cte
order by restaurant, month;
Here is a db<>fiddle.
GROUP BY & SUM of values with missing MONTHS
You need to move condtition to ON
:
-- ...
SELECT
[Period] = CONVERT(VARCHAR(4),YEAR(d.d)) +'-'+ CONVERT(VARCHAR(2), MONTH(d.d)),
QtyTotal = ISNULL(SUM(o.QEXIT),0)
FROM d LEFT OUTER JOIN VE_STOCKTRANS AS o
ON o.TRANSDATE >= d.d
AND o.TRANSDATE < DATEADD(MONTH, 1, d.d)
AND STOCKID = 6000 AND TRANSTYPE = 3553 -- here
GROUP BY d.d
ORDER BY d.d;
TSQL - fill out missing months with totals
All you need to do is to transform the rows from Amount so that they encompass the range in which they're valid and then join them to the calendar table.
The rows will implicitly have the start date in the YearMonth column. To get the cutoff date, you can use the LEAD window function to get the date from the next row in order. If there is no next row, then just add 1 to the current row's YearMonth so that only that row is used.
SELECT amt.Employee, amt.Reference_no, cal.YearMonth, amt.Amount
FROM (
SELECT *,
LEAD(YearMonth, 1, YearMonth + 1)
OVER (PARTITION BY Employee, Reference_no ORDER BY YearMonth) [Cutoff]
FROM Amount
) amt
INNER JOIN Calendar cal ON cal.YearMonth >= amt.YearMonth AND cal.YearMonth < amt.Cutoff
How to fill data for missing months for more than 1 year
If you have a Projects table in your database:
select ProjectNo, Period, IsNull(wip, 0) wip , IsNull(billing, 0) billing
from Projects d1
outer apply (
select m.*,d2.wip, d2.billing
from Months m
left join ProjectReportData d2 on m.Period = d2.Period and d2.ProjectNo=d1.ProjectNo
) mm
order by 1, 2 desc
If you don't have a Projects table in your database:
select ProjectNo, Period, IsNull(wip, 0) wip , IsNull(billing, 0) billing
from (
select distinct ProjectNo
from ProjectReportData
) d1
outer apply (
select m.*,d2.wip, d2.billing
from Months m
left join ProjectReportData d2 on m.Period = d2.Period and d2.ProjectNo=d1.ProjectNo
) mm
order by 1, 2 desc
T-SQL Running Monthly Totals Including Missing Months
DECLARE @start_date date, @end_date date
SELECT @start_date='2012-04-01',@end_date='2013-03-31'
;WITH xo AS
(
SELECT @start_date AS cte_start_date
UNION ALL
SELECT DATEADD(MONTH, 1, cte_start_date)
FROM xo
WHERE DATEADD(MONTH, 1, cte_start_date) <= @end_date
), x as (
select *,row_number() over (order by cte_start_date) monthno
from xo
)
, y as (
select distinct handler from test
)
SELECT y.handler, datename(mm,x.cte_start_date), x.monthno
,(select sum(mtd) from test a where a.handler=y.handler and a.monthno<=x.monthno) mtd
FROM y
cross join x
order by 1,3
see example on SQLFiddle http://sqlfiddle.com/#!3/7d483/15
Related Topics
Change Column Types in a Huge Table
Sqlite Multi-Primary Key on a Table, One of Them Is Auto Increment
SQL Select Rows with Only a Certain Value in Them
SQL Statement Help - Select Latest Order for Each Customer
How to Rename an Index in MySQL
SQL Select Max(Date) and Corresponding Value
Add Row Number to This T-SQL Query
SQL Server: How to Know If Any Row Is Referencing the Row to Delete
Oracle SQL: How to Use More Than 1000 Items Inside an in Clause
Calculate Row Wise Sum - SQL Server
Best-Performance Query for "Select Max in Group"
How to Select the Most Frequently Appearing Values
Arithmetic Overflow Error Converting Numeric to Data Type Numeric
Extracting the Total Number of Seconds from an Interval Data-Type
How to Select Columns from a Table Which Have Non Null Values