How to sum previous month values and current month values in SQL query - sql

Please help me to solve this issue. I have to write a query to get the sum of previous month values and current month values but not able to get the solution.
Here is an image for your reference sum of actual count column values I need the result.

In Oracle you would use the following, could be not completely correct on the case statement:
Select
Site,
sum(value * (case (date_transaction > trunc(sysdate, 'MM') then 1 else 0 end))
volume_current_month
from myTable
where date_transaction between add_months(trunc(sysdate,'MM'),-1) and sysdate
group by site
The previous month is more or less the same using another case statement and ADD_MONTHS.

There are two ways to do this in Tableau :
First Way .
Under Analysis --> Total --> Add All SubTotals .
Second Way :
Create a calc field Total_event as :
WINDOW_SUM(SUM([Event Count]))
Compute the Window_sum as COMPUTE USING EVENT NAME .

If you CAN USE sql AND YOU actually need the previous month and not just all months summed by EventName then you could use LAG. I made the assumption that you are summing by EventName and you only want the current EventName and previous EventNAme
WITH Summed
AS
(
SELECT * ,
LAG(EventCount) OVER (Partition BY EventName ORDER BY trialmonth) as PrevEvent
FROM dbo.Table1
)
SELECT *,
SUM(PrevEvent+EventCount) AS SummedCount
FROM summed
GROUP BY Site
,TrialMonth
,EventName
,EventCount
, PrevEvent
This will produce output like this
Site TrialMonth EventName EventCount PrevEvent SummedCount
12101 2001-10-15 Actual Count 4 NULL NULL
12101 2001-10-15 Projected Count 8 NULL NULL
12101 2001-11-15 Actual Count 6 4 10
12101 2001-11-15 Projected Count 9 8 17
12101 2001-12-15 Actual Count 0 6 6
12101 2001-12-15 Projected Count 10 9 19
http://sqlfiddle.com/#!6/8253f0/2

In tableau -> Create a calculated field ->
// This is for previous month
if [date] >= DATE("01" +"-" + (Month(TODAY())-1) +"-" + YEAR(TODAY()))
and [date] <= DATE("31" +"-" + (Month(TODAY())-1) +"-" + YEAR(TODAY()))
//if the month has 30 or 28 days it will check that there is no 31 and return null
then
sum([Value])
end
//For current month ->
if Month([date]) = Month(TODAY()) then
sum([Value])
end
You will 2 fields returning previous month's sum and current month's sum, You can then use them as you wish.
On sql end you may use
For Previous Month ->
select sum(value) from table_name t where DATE_PART('month',t.date)=DATE_PART('month',TIMESTAMPADD(mm,-1,GETDATE()))
For current Month ->
select sum(value) from table_name t where DATE_PART('month',t.date)=DATE_PART('month',GETDATE()))

Related

Between numerical values with no lower limit in Oracle SQL

My data looks something similar to:
days
weight
start date
end date
180
1
01/01/2020
null
365
0.75
01/01/2020
null
And I want to be able to select this to assign the correct value where say if the days were 0-180, they would be row 1 and 181-365 it would be row 2. If it was 365+ it would be row 2. I have already found out I can use between sql syntax for the date.
My initial code tries to do this:
select weight from (select * from table where days >= #DAYS order by days ASC) where rownum =1
But then if you do more than the last value it doesn't show anything so i've then tried to introduce a maximum element trying to find the maximum value and saying
>= #DAYS
or
>= MAX(#DAYS)
Is there a simpler way to do this?
Thanks.
select weight
from (select t.*, max(days) over () as max_day from table t) v
where days >= least(#DAY,max_day)
order by days asc
fetch first 1 row only
I'd suggest this option. When #DAY becomes larger than the largest days entry, we use max_days instead.
Select max(weight) from table
Where days=(Select max(days) from table
Where days >= #DAYS)
The first max() function is defensive in case your table has 2 entries with the same days number.

Count previous 24 months rows based on condition from current row

How to count the previous 24 months from a current row based on principalreliefflag(It should be based on each row (each month with previous 24 months). So count principal flag(Y) from current row to previous 24 months.)?
Data I have:
Data I need:
Code:
-------------------------------------------------------------------------
----Identify customers who are on principal relief more than one month
-------------------------------------------------------------------------
IF OBJECT_ID('tempdb..##PRappliedmorethan_once') IS NOT NULL
DROP TABLE ##PRappliedmorethan_once
select *,
case when PrincipalReliefFlag='Y' then 1 else 0
end PR_applied_months
into ##PRappliedmorethan_once
from ##TL_details_dates2
IF OBJECT_ID('tempdb..##PRappliedmorethan_once1') IS NOT NULL
DROP TABLE ##PRappliedmorethan_once1
select *,
--Identify customers who have applied for principal relief within the past 12 months
sum(PR_applied_months) over (partition by productitemcode, productcode
order by dim_snapshotdate_key
rows between 23 preceding and current row
)
abcd
into ##PRappliedmorethan_once1
from ##PRappliedmorethan_once
It works but is there any better way?
Try using the DATEDIFF() function to check the last 24 months e.g. :
SELECT COUNT(*) FROM YOUR_TABLE
WHERE DATEDIFF(month, current_row_date, date_to_be_compared) <= 24

Running total with Over

I'm trying to create a running total of the number of files per opened by day so I can use the data for a graph showing cumulative results.
The data is basically the file opening date, a calculated field showing 'This month' or 'Last Month' depending on the date and the running total field that I'm trying to figure out.
Date Month Count
==== ===== =====
2019-08-01 Last Month 6
2019-08-02 Last Month 2
2019-08-03 Last Month 5
I want to have a running total...so 6, 8, 13 etc
But all I'm getting is a row count (1,2,3 etc) for my count field.
select
FileDate,
Month,
sum(Count) OVER(PARTITION BY month order by Filedate) as 'Count'
from (
select
1 as 'Count',
Case
When month(cast(concat(right(d.var_val,4),substring(d.var_val,4,2),left(d.var_val,2)) as DATE) ) = Month(getdate()) then 'This Month'
else 'Last Month'
end as 'Month'
FROM data d
left join otherdata m on d.VAR_FileID = m.MAT_FileID
left join otherdata u on m.MAT_Fee_Earner = u.User_ID
left join otherdata br on m.MAT_BranchID = br.BR_ID
WHERE d.var_no IN ( '1628' )
and Len(var_val) = 10
)files
where Month(FileDate) in (MONTH(FileDate()),MONTH(getDate())-1)
and Year(Filedate) = Year(Getdate())
and Dept = 'Peterborough Property'
group by Month, FileDate, count
GO
I'm assuming I've not quite grasped the proper usage of 'OVER' - any pointers would be great!
The Partition clause indicates when to reset the count, so by partitioning by month you are only counting records for each discreet month to get a running total, over the whole dataset, you don't want the partition clause at all, just the order by clause.
Hope your clear with OVER clause now (with "Sentinel" answer), in which case you should replace desired column as follows, so that count continuously increase for all the rows from sub-query based on order by clause: for more details on OVER Clause..
sum(Count) OVER (Oder by Filedate) as [Count]
-- or
sum(Count) OVER (Oder by Filedate desc) as [Count]

Find Distinct IDs when the due date is always on the last day of each month

I have to find distinct IDs throughout the whole history of each ID whose due dates are always on the last day of each month.
Suppose I have the following dataset:
ID DUE_DT
1 1/31/2014
1 2/28/2014
1 3/31/2014
1 6/30/2014
2 1/30/2014
2 2/28/2014
3 1/29/2016
3 2/29/2016
I want to write a code in SQL so that it gives me ID = 1 as for this specific ID the due date is always on the last day of each given month.
What would be the easiest way to approach it?
You can do:
select id
from t
group by id
having sum(case when extract(day from due_dt + interval '1 day') = 1 then 1 else 0 end) = count(*);
This uses ANSI/ISO standard functions for date arithmetic. These tend to vary by database, but the idea is the same in all databases -- add one day and see if the day of the month is 1 for all the rows.
If your using SQL Server 2012+ you can use the EOMONTH() function to achieve this:
SELECT DISTINCT ID FROM [table]
WHERE DUE_DT = EOMONTH(DUE_DT)
http://rextester.com/VSPQR78701
The idea is quite simple:
you are on the last day of the month if (the month of due date) is not the same as (the month of due date + 1 day). This covers all cases across year, leap year and so on.
from there on, if (the count of rows for one id) is the same as (the count of rows for this id which are the last day of the month) you have a winner.
I tried to write an example (not tested). You do not specify which DB so I will assume that cte (common table expression) are available. If not just put the cte as subquery.
In the same way, I am not sure that dateadd and interval work the same in all dialect.
with addlastdayofmonth as (
select
id
-- adding a 'virtualcolumn', 1 if last day of month 0 otherwise
, if(month(dateadd(due_date, interval '1' day)) != month(due_date), 1 ,0) as onlastday
from
table
)
select
id
, count(*) - sum(onlastday) as alwayslastday
from
addlastdayofmonth
group by
id
having
-- if count(rows) == count(rows with last day) we have a winner
halwayslastday = 0
MySQL-Version (credits to #Gordon Linoff)
SELECT
ID
FROM
<table>
GROUP BY
ID
HAVING
SUM(IF(day(DUE_DT + interval 1 Day) = 1, 1, 0)) = COUNT(ID);
Original Answer:
SELECT MAX(DUE_DT) FROM <table> WHERE ID = <the desired ID>
or if you want all MAX(DUE_DT) for each unique ID
SELECT ID, MAX(DATE) FROM <table> GROUP BY ID

Sort Numbers in varchar value in SQL Server

My Goal is to load a monthly-daily tabular presentation of sales data with sum total and other average computation at the bottom,
I have one data result set with one column that is named as 'Day' which corresponds to the days of the month, with automatic datatype of int.
select datepart(day, a.date ) as 'Day'
On my second result set, is the loading of the sum at the bottom, it happens that the word 'Sum' is aligned to the column of Day, and I used Union All TO COMBINE the result set together, expected result set is something to this like
day sales
1 10
2 20
3 30
4 10
5 20
6 30
.
.
.
31 10
Sum 130
What I did is to convert the day value, originally in int to varchar datatype. this is to successfully join columns and it did, the new conflict is the sorting of the number
select * from #SalesDetailed
UNION ALL
select * from #SalesSum
order by location, day
Assuming your union query returns the correct results, just messes up the order, you can use case with isnumeric in the order by clause to manipulate your sort:
SELECT *
FROM
(
SELECT *
FROM #SalesDetailed
UNION ALL
SELECT *
FROM #SalesSum
) u
ORDER BY location,
ISNUMERIC(day) DESC,
CASE WHEN ISNUMERIC(day) = 1 THEN cast(day as int) end
The isnumeric will return 1 when day is a number and 0 when it's not.
Try this
select Day, Sum(Col) as Sales
from #SalesDetailed
Group by Day With Rollup
Edit (Working Sample) :
select
CASE WHEN Day IS NULL THEN 'SUM' ELSE STR(Day) END as Days,
Sum(Sales) from
(
Select 1 as Day , 10 as Sales UNION ALL
Select 2 as Day , 20 as Sales
) A
Group by Day With Rollup
EDIT 2:
select CASE WHEN Day IS NULL THEN 'SUM' ELSE STR(Day) END as Days,
Sum(Sales) as Sales
from #SalesDetailed
Group by Day With Rollup