How do I incorporate a Double Moving Average in straight SQL in a single query? - sql

EDIT: I need to do this in ACCESS.
I am an SQL virgin and would greatly appreciate any magical assistance!
For a simple 12 month forecast, I am utilizing a 12 month Double Moving Average.
I have managed to pull the Single Moving Average through Query 1 (below).
Based on the table created by Query 1, I have written another query (Query 2) to get the Double Moving Average.
As such, my current process requires two queries. My efforts so far to combine these two steps into a single query have not been successful.
My Question: Is there any way to calculate Double Moving Average in a single query?
QUERY 1 - For Single Moving Average:
SELECT A.*, IIf([A].[VOL]>0,
(SELECT AVG(B.[VOL])
FROM [Turnover] as B
WHERE (B.Code = A.Code) AND (B.YM Between A.YM - 1 AND A.YM - ([12] * 31))),
(SELECT AVG(B.[VOL])
FROM [Turnover] as B
WHERE (B.Code = A.Code) AND (B.YM Between Now() - 31 AND A.YM - ([12] * 31)))) AS [Mvg Avg 1],
INTO [Model 12m]
FROM [Turnover] AS A;
QUERY 2 - Double Moving Average (currently this refers to QUERY 1):
SELECT A.*, IIf([A].[Mvg Avg 1]>0,(SELECT AVG(B.[Mvg Avg 1])
FROM [Model 12m] as B
WHERE (B.Code = A.Code) AND (B.YM Between A.YM - 1 AND A.YM - ([12] * 31))),(SELECT AVG(B.[Mvg Avg 1])
FROM [Model 12m] as B
WHERE (B.Code = A.Code) AND (B.YM Between Now() - 31 AND A.YM - ([12] * 31)))) AS [2 Mvg Avg],
INTO [Model 12m - 2MA]
FROM [Model 12m] AS A;

My Question: Is there any way to calculate Double Moving Average in a
single query?
Since you're using Microsoft Access, there should be no need to do that. Save the first query as a new query. (For people who don't use MS Access, saving the SQL statement as a new query is equivalent to the SQL statement CREATE VIEW ....) Then use the second query as-is, or save it as another new query.
MS Access is really good at optimizing queries built on queries (views built on views).

Related

How to write SQL to calculate running average with some additional formulae?

Following is the image that has running average calculated by me. But the requirement is a bit extra on top of the running average.
Following is the image where the requirement is in the Microsoft Excel sheet.
So, in order to calculate the running average with formulae like =(3*C4+2*C5+1*C6)/6 that have been gathered in excel sheet, what SQL Query could be written?
Also, if it's not feasible through SQL, then how could I use the Column D from the second image as my measure in SSAS?
use LAG() with offset and follow your formula accordingly
avg_val = ( (3.0 * lag(Open_, 2) over (order by M, [WEEK]) )
+ (2.0 * lag(Open_, 1) over (order by M, [WEEK]) )
+ (1.0 * Open_) ) / 6

How to get the difference between two lines

thanks for help
I have the following table in PostgreSQL
The columns are
ON = END - START
IDLE = START (LINE 2) - END (LINE 1)
I need calculate "idle" using select ... The idle value is obtained using the start of line 2 subtracted from the end of line 1, following the example, the idle value 00:25 is 09:25 - 09:00.
I'm not able to create a logic for this, or the code for calculate it.
Here is my select
select st.id,
st.tvd_unidade,
st.tvd_pdv,
st.tvd_cupom,
st.tvd_operador,
min(st.tvd_data_hora) as start_at,
max(en.tvd_data_hora) as end_at,
max(en.tvd_data_hora) - min(st.tvd_data_hora) as produtivo
from ger st
inner join ger en on st.tvd_unidade = en.tvd_unidade and st.tvd_pdv = en.tvd_pdv and st.tvd_cupom = en.tvd_cupom
where en.tvd_tipo_reg in ('FINN','FINn')
and st.tvd_tipo_reg in ('INFN','INFn')
group by 1
Before you worry about the maths, you need to be able to see all the data you need on one row. To see data from other rows, you use windowing functions. In this case, you could use the lag windowing function to look at the previous row - something like this
Select start, end, lag(end) over (order by [your sort key]) as lastEnd
from table
order by [your sort key]
should give you the data you need. Once you're sure you've got the right data, then you can start doing the maths calculations for on and idle

SQL query - mod function - how can I use it to group results?

I'm very new to querying so apologies if this is a simple question. Note this question is related to Microsoft Query as I am pulling the results through to a report.
I currently have a table with a number of columns, including one column that is an integer value between 1 and 6. I am trying to group by on this column based on whether the value in the column is even or odd but am just not sure how to accomplish this given my knowledge (a bit of background as to why I want this: the table I am using relates to timesheet entries with the shift column I am referring to having odd values for day shift and even values for night shift). If someone could help this would be great. Currently, I have the following code:
SELECT
PRTH.PostDate, HRRM.LastName, HRRM.FirstName,
Sum(PRTH.Hours) AS 'Sum of Hours',
(PRTH.Shift Mod 2) As 'Night Shift'
FROM
Viewpoint.dbo.HRRM HRRM, Viewpoint.dbo.PRTH PRTH
WHERE
PRTH.Employee = HRRM.PREmp AND PRTH.JCCo = HRRM.PRCo
GROUP BY
PRTH.PostDate, HRRM.LastName, HRRM.FirstName, Night Shift
It is the Mod function that I am having trouble with as I am not sure how to define this and then also how to use this in the group by function.
Thanks in advance
It sounds like this is what you're looking for -- use the % operator to perform a Mod:
select a % 2, sum(b)
from yourtable
group by a % 2
Condensed SQL Fiddle Demo
To apply this to your query, try this:
SELECT PRTH.PostDate, HRRM.LastName, HRRM.FirstName,
Sum(PRTH.Hours) AS 'Sum of Hours', (PRTH.Shift % 2) As 'Night Shift'
FROM Viewpoint.dbo.HRRM HRRM
INNER JOIN Viewpoint.dbo.PRTH PRTH
ON PRTH.Employee = HRRM.PREmp AND PRTH.JCCo = HRRM.PRCo
GROUP BY PRTH.PostDate, HRRM.LastName, HRRM.FirstName, PRTH.Shift % 2
Also notice, I replaced your Joins with the INNER JOIN syntax -- this is preferable. See this post for more information (https://stackoverflow.com/a/1018825/1073631)

SQL Percercentile Calculation

I have the following query, which even without a ton of data (~3k rows) is still a bit slow to execute, and the logic is a bit over my head - was hoping to get some help optimizing the query or even an alternate methodology:
Select companypartnumber, (PartTotal + IsNull(Cum_Lower_Ranks, 0) ) / Sum(PartTotal) over() * 100 as Cum_PC_Of_Total
FROM PartSalesRankings PSRMain
Left join
(
Select PSRTop.Item_Rank, Sum(PSRBelow.PartTotal) as Cum_Lower_Ranks
from partSalesRankings PSRTop
Left join PartSalesRankings PSRBelow on PSRBelow.Item_Rank < PSRTop.Item_Rank
Group by PSRTop.Item_Rank
) as PSRLowerCums on PSRLowerCums.Item_Rank = PSRMain.Item_Rank
The PartSalesRankings table simply consists of CompanyPartNumber(bigint) which is a part number designation, PartTotal(decimal 38,5) which is the total sales, and Item_Rank(bigint) which is the rank of the item based on total sales.
I'm trying to end up with my parts into categories based on their percentile - so an "A" item would be top 5%, a "B" item would be the next 15%, and "C" items would be the lower 80th percentile. The view I created works fine, it just takes almost three seconds to execute, which for my purposes is quite slow. I narrowed the bottle neck to the above query - any help would be greatly appreciated.
The problem you are having is the calculation of the cumulative sum of PartTotal. If you are using SQL Server 2012, you can do something like:
select (case when ratio <= 0.05 then 'A'
when ratio <= 0.20 then 'B'
else 'C'
end),
t.*
from (select psr.companypartnumber,
(sum(PartTotal) over (order by PartTotal) * 1.0 / sum(PartTotal) over ()) as ratio
FROM PartSalesRankings psr
) t
SQL Server 2012 also have percentile functions and other functions not in earlier versions.
In earlier versions, the question is how to get the cumulative sum efficiently. Your query is probably as good as anything that can be done in one query. Can the cumulative sum be calculated when partSalesRankings is created? Can you use temporary tables?

Simplify query in H2 database - alternative to TOP X PERCENT

I'm having performance issues with a query and was wondering how to simplify it.
I have a table "Evaluations" (Sample, Category, Jury, Value)
And created some custom functions to get some average values for each sample, so I have this view:
CREATE VIEW Results AS
SELECT Sample,
Category,
IFNULL(COUNT_VALID(Value),0) || ' / ' || COUNT(Value) AS Valid,
CUSTOM_MEAN(Value) AS Mean,
CUSTOM_MEDIAN(Value) AS Median
FROM Evaluations GROUP BY Sample, Category;
Then I want to have another field telling me if each sample is within the 30% of best valued samples of its category. It would be perfect to use TOP(X) PERCENT but it seems H2 doesn't support it so I made a second view that calculates the position in category multiplied by 100, divided by the total count in category and compared to 30:
CREATE VIEW Res AS
SELECT R1.*,
CASE
WHEN (
((SELECT COUNT(*) FROM Results R2
WHERE R2.Category = R1.Category
AND (R2.Mean > R1.Mean OR (R2.Mean = R1.Mean AND R2.Median > R1.Median))) + 1) * 100
/
(SELECT COUNT(*) FROM Results R2 WHERE R2.Category = R1.Category) )
> 30
THEN 'over 30%'
ELSE 'within 30%'
END as 30PERCENT
FROM Results R1 ORDER BY Mean DESC, Median DESC;
This works properly but with just 500 records it takes some time to retrieve the results.
Could someone tell me a more efficient way of constructing this query?
Thanks and regards!