I have a table with two fields
DATE_YYYYMM
TOTAL
That table contains the accumulated total per month for the whole year.
I'd like a query retrieving the "unacumulated" total for each month.
For example, the total of 201806 would be equal to the total of 201806 minus the one of 201805.
Any tip please ? Thanks !
The window function LAG can be used to get a previous value based on an order.
And it seems you just want to subtract the previous month's total from the total.
SELECT
DATE_YYYYMM,
TOTAL,
TOTAL - ISNULL(LAG(TOTAL) OVER (ORDER BY DATE_YYYYMM), 0) AS UNACCUMULATED
FROM YourYearTotalsTable
You can use the analytic function LAG (starting from sql-server-2012) to compare values in the current row with values in a previous row.
SELECT
[date_yyyymm]
,[current_total] = [total]
,[previous_total] = LAG([total], 1, 0) OVER (ORDER BY [date_yyyymm])
,[unacumulated] = [total] - LAG([total], 1, 0) OVER (ORDER BY [date_yyyymm])
FROM [your_table]
ORDER BY [date_yyyymm];
Related
I have a dataset with the following columns
city
user
week
month
earnings
Ideally I want to calculate a 50th % from percentile_cont(earnings,0.5) over (partition by city order by month range between 1 preceding and current row). But Big query doesn't support window framing in percentile_cont. Can anyone please help me if there is a work around this problem.
If I understand correctly, you can aggregate into an array and then unnest:
select t.*,
(select percentile_cont(earning) over ()
from unnest(ar_earnings) earning
limit 1
) as median_2months
from (select t.*,
array_agg(earnings) over (partition by city
order by month
range between 1 preceding and current month
) as ar_earnings
from t
) t;
You don't provide sample data, but this version assumes that month is an incrementing integer that represents the month. You may need to adjust the range depending on the type.
I have a use case function that needs to returns a single row only for every end of month.
I tried using select distinct and it is showing multiple records for the same end of month
SELECT DISTINCT CASE
WHEN eff_interest_balance < 0.01 THEN trial_balance_date
WHEN date_paid < trial_balance_date THEN date_paid
END as A
, period
FROM dbo.Intpayments[enter image description here][1]
WHERE loan_number = 60023
ORDER BY period ASC
Each row should return single date for each month
Distinct is returning unique rows, not grouping them. You are looking to aggregate rows. This means using some combination of aggregate functions and group by.
What your current query is missing is some sort of logic for aggregating the rows that are in the same period. Do you want to compare the sum of these values? The min, the max?
In any case, the basic idea of aggregating and grouping would look like this - I don't think this summing is what you want, but the query shows the basic idea of aggregating and grouping:
SELECT
period
, SUM(eff_interest_balance) AS SumOfBalance
FROM dbo.Intpayments
WHERE loan_number = 60023
GROUP BY period
I have a table with SentDate and RefundAmounts. I would like to sum up the amounts on each row from the date until a year into the future for every line.
In the example below I would like to add a column that says sum for the year.
This sum should be for the first line the sum of refunds from '2006-12-14' until '2007-12-14' which would be 3696,22 as there were no refunds during that period.
The second row would be from '2007-12-24' until '2008-12-24' which would be 463,05
SentDate YearAhead RefundAmount
2006-12-14 2007-12-14 3696,22
2007-12-24 2008-12-24 394,35
2008-12-18 2009-12-18 44,33
2008-12-19 2009-12-19 24,37
2009-12-16 2010-12-16 21,88
I have tried something along the lines of
select SentDate, dateadd(year,1,sentdate) YearAhead, SumRefund
from table
but I have no idea how to get the annual future sum for each row
Thanks for the suggestion. The final result should look as follows:
SentDate YearAhead RefundAmount SumForYear
2006/12/14 2007/12/14 3696,22 3696,22
2007/12/24 2008/12/24 394,35 463,05
2008/12/18 2009/12/18 44,33 90,58
2008/12/19 2009/12/19 24,37 46,25
2009/12/16 2010/12/16 21,88 21,88
You need to join with a BETWEEN to gather all rows that compose that period, then use GROUP BY with SUM to the result.
select
T.SentDate,
dateadd(year, 1, T.SentDate) YearAhead,
SUM(P.SumRefund) AS TotalOverYear
from
YourTable AS T
INNER JOIN YourTable AS P ON P.SentDate BETWEEN T.SendDate AND DATEADD(YEAR, 1, T.SendDate)
GROUP BY
T.SentDate
Something like this should suite your needs if you always need a complete year:
select sum(refund) as refundAmounts,year(min(SentDate)) as year from yourTable group by year(SentDate)
the year function gets only the year part from a datetime row and with group by you can split the aggregation of sum and min function to different groups.
I want to incorporate two average calculations for a bunch of value columns in my select statement.
see this link for my simplified table structure including the desired output calculation: Pastebin
1) moving average:
Month1 = value of the value1-column for that month, Month2 = if sum == 0 then write 0, else avg(Month1 and Month2) and so on.
So for each product, I want the moving average for each month within one year.
I have this set up in my Excel but I can't transfer the expression to sql.
2) overall average:
for each product, calculate the average over all years and duplicate the calculated value to all rows for that product.
I hope you can help me out with this. It looks like I need a procedure but maybe it is just a simple statement.
SQL-Server 2012 supports the analytic functions required to do this:
SELECT Product,
Month,
Year,
Value,
AVG_YTD = AVG(Value) OVER(PARTITION BY Year ORDER BY Month),
AVG_Year = AVG(Value) OVER(PARTITION BY Product, Year),
AVG_Overall = AVG(Value) OVER(PARTITION BY Product)
FROM T;
Simplified Example on SQL Fiddle
I want to see if the price of a stock has changed by 5% this week. I have data that captures the price everyday. I can get the rows from the last 7 days by doing the following:
select price from data where date(capture_timestamp)>date(current_timestamp)-7;
But then how do I analyze that and see if the price has increased or decreased 5%? Is it possible to do all this with one sql statement? I would like to be able to then insert any results of it into a new table but I just want to focus on it printing out in the shell first.
Thanks.
It seems odd to have only one stock in a table called data. What you need to do is bring the two rows together for last week's and today's values, as in the following query:
select d.price
from data d cross join
data dprev
where cast(d.capture_timestamp as date = date(current_timestamp) and
cast(dprev.capture_timestamp as date) )= cast(current_timestamp as date)-7 and
d.price > dprev.price * 1.05
If the data table contains the stock ticker, the cross join would be an equijoin.
You may be able to use query from the following subquery for whatever calculations you want to do. This is assuming one record per day. The 7 preceding rows is literal.
SELECT ticker, price, capture_ts
,MIN(price) OVER (PARTITION BY ticker ORDER BY capture_ts ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS min_prev_7_records
,MAX(price) OVER (PARTITION BY ticker ORDER BY capture_ts ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS max_prev_7_records
FROM data