Crosstab query to only show the previous 4 weeks - ms-access

I am open to suggestions on changing the way I have started to lay out my data.
What I need:
I need to display a list of individuals performance week on week. To do this I have created a crosstab query with each column showing as the date (built using the query wizard).
The query actually functions fine, although I only want to show 4 columns (being 4 weeks worth of data) but really don't know where to start giving me doubt that I have taken the correct approaching using a cross tab.
because there is no conditioning its showing the full year being almost over 50 columns
Current Code:
TRANSFORM Max(tbl_Genesys_Weekly.[Field32]) AS MaxOfField32
SELECT [_tbl_Structure].[User Name]
FROM _tbl_Structure INNER JOIN tbl_Genesys_Weekly ON [_tbl_Structure].[User ID] = tbl_Genesys_Weekly.Field5
GROUP BY [_tbl_Structure].[User Name]
ORDER BY tbl_Genesys_Weekly.WC_Date
PIVOT tbl_Genesys_Weekly.WC_Date;
Any help is hugely appreciated
UPDATED CODE:
TRANSFORM Max(Format([Field32]/100,"Percent")) AS Calc
SELECT [_tbl_Structure].CSM, [_tbl_Structure].[User Name]
FROM _tbl_Structure INNER JOIN tbl_Genesys_Weekly ON [_tbl_Structure].[User ID] = tbl_Genesys_Weekly.Field5
GROUP BY [_tbl_Structure].CSM, [_tbl_Structure].[User Name]
ORDER BY tbl_Genesys_Weekly.WC_Date DESC
PIVOT DatePart("ww", tbl_Genesys_Weekly.WC_Date)
WHERE DateDiff("ww", tbl_Genesys_Weekly.WC_Date, Date()) Between 5 and 1;
ERROR RECEIVED:
Characters found after end of SQL statement

You could use:
PIVOT DatePart("ww", tbl_Genesys_Weekly.WC_Date);
and include a where clause:
WHERE DateDiff("ww", tbl_Genesys_Weekly.WC_Date, Date()) Between 5 and 1
Note, that if you use standard ISO 8601 weeknumbers, DatePart cannot be used, and the year will have to included to obtain the correct sorting around New Year.

Related

Calculate Sum of Mean and Std dev in sql query on single column

I am having table name as "Table1" in mysql.I have to find Sum of Mean and Std dev on column "Open".I did it easily using python but I am unable to do it using sql.
Select * from BANKNIFTY_cal_spread;
Date Current Next difference
2021-09-03 00:00:00 36914.8 37043.95 129.14999999999418
2021-09-06 00:00:00 36734 36869.15 135.15000000000146
2021-09-07 00:00:00 36572.9 36710.65 137.75
2021-09-08 00:00:00 36945 37065 120
2021-09-09 00:00:00 36770 36895.1 125.09999999999854
Python Code-
nf_fut_mean = round(df['difference'].mean())
print(f"NF Future Mean: {nf_fut_mean}")
nf_fut_std = round(df['difference'].std())
print(f"NF Future Standard Deviation: {nf_fut_std}")
upper_range = round((nf_fut_mean + nf_fut_std))
lower_range = round((nf_fut_mean - nf_fut_std))
I search for Sql solution but I didn't get it. I tried building query but it's not showing correct results in query builder in grafana alerting.
Now I added Mean column ,std dev column , upper_range and lower_range column using python dataframe and pushed to mysql table.
#Booboo,
After removing Date from SQL Query, it's showing correct results in two columns- average + std_deviation and average - std_deviation.
select average + std_deviation, average - std_deviation from (
select avg(difference) as average, stddev_pop(difference) as std_deviation from BANKNIFTY_cal_spread
) sq
It looks as though the sample you're using for the aggregations for MEAN, STDDEV, etc is the entire table - in which case you have to drop the DATE field from the query's result set.
You could also establish the baseline query using a CTE (Common Table Expression) using a WITH statement instead of a subquery, and then apply the subsequent processing:
WITH BN_CTE AS
(
select avg(difference) as average, stddev_pop(difference) as std_deviation from BANKNIFTY_cal_spread
)
select average + std_deviation, average - std_deviation from BN_CTE;
With the data you posted having only a single Open column value for any given Date column value, you standard deviation should be 0 (and the average just that single value).
I am having difficulty in understanding your SQL since I cannot see how it relates to finding the sum (and presumably the difference, which you also seem to want) of the average and standard deviation of column Open in table Table1. If I just go by your English-language description of what you are trying to do and your definition of table Table1, then the following should work. Note that since we want both the sum and difference of two values, which are not trivial to calculate, we should calculate those two values only once:
select Date, average + std_deviation, average - std_deviation from (
select Date, avg(Open) as average, stddev_pop(Open) as std_deviation from Table1
group by Date
) sq
order by Date
Note that I am using column aliases in the subquery that do not conflict with built-in MySQL function names.
SQL does not allow both calculating something in the SELECT clause and using it. (Yes, #variables allow in limited cases; but that won't work for aggregates in the way hinted in the Question.)
Either repeat the expressions:
SELECT average(difference) AS mean,
average(difference) + stddev_pop(difference) AS "mean-sigma",
average(difference) - stddev_pop(difference) AS "mean+sigma"
FROM BANKNIFTY_cal_spread;
Or use a subquery to call the functions only once:
SELECT mean, mean-sigma, mean+sigma
FROM ( SELECT
average(difference) AS mean,
stddev_pop(difference) AS sigma
FROM BANKNIFTY_cal_spread
) AS x;
I expect the timings to be similar.
And, as already mentioned, avoid using aliases that are identical to function names, etc.

Where is the Syntax Error in this MS Access Nested IIF with Parameters Query?

I am trying to create a query in Access that sums the number of Projects Under Consideration and Development as a Month End Inventory. There are three fields I need to get that number dtCreate, dtLegalEnd, and dtFinalClosed, but I also need the code to be dynamic so that it can pull that same sum for a give month, months and years after it has passed. So I tried to do it has a nested IIF parameter query with the following syntax:
SELECT sum(IIF([tblProjectsA].[dtCreate]>[Enter Date End of Month],0,sum(IIF([tblProjectsA].[dtLegalEnd]>[Enter Date End of Month] or is null,0,Sum(IIF([tblProjectsA].[dtFinalClosed]>[Enter Date End of Month] or is null,0,1))))))
FROM tblProjectsA;
Where is my syntax error(s)? Is there a better way to achieve the same result or have the results for each mm/yyyy query?
Thanks,
Meg
Try
SELECT sum(IIF([tblProjectsA].[dtCreate]>[Enter Date End of Month],0,sum(IIF([tblProjectsA].[dtLegalEnd]>[Enter Date End of Month]
or [tblProjectsA].[dtLegalEnd] is null,0,Sum(IIF([tblProjectsA].[dtFinalClosed]>[Enter Date End of Month] or [tblProjectsA].[dtFinalClosed] is null,0,1)))))) FROM tblProjectsA;
As for having results for each mm/yyyy, you should use GROUP BY clause, like
SELECT Month([your date]) AS Month, Year([your date]) AS Year, ...
FROM ...
GROUP BY Month([your date]), Year([your date])
The error is caused because you are summing a sum. Sum is an sql function that if Sum(column) where column has 5 rows that all = 1, then Sum will return 5. When you try to call sum inside sum Access doesn't officially know what column to pass to the inner sum to get a value to put in the outer sum. So Access throws an error, you can tell access to calculate the inner sum first by wrapping it in a subquery.
But I find subqueries are harder to understand and don't have good Access designer support. So instead I use calculated fields which I find more intuitive and declaritive.
ProjectUnderConsideration: IIf(([dtCreate]<[MonthEnd]) And ([dtFinalClosed]<[MonthEnd]) And (([dtLegalEnd]<[MonthEnd]) Or IsNull([dtLegalEnd])),1,0)
I don't understand the construct of ProjectUnderConsideration. Adjust this explanation to your actual case. I assumed a project is under consideration if dtCreate, dtLegalEnd, and dtFinalClosed are all < MonthEnd. and for demonstration I assumed dtLegalEnd could be null.
You can use the Designer in Access to help you write and test your sql:
'sql
PARAMETERS MonthEnd DateTime;
SELECT tblProjectsA.dtCreate, tblProjectsA.dtLegalEnd, tblProjectsA.dtFinalClosed, IIf(([dtCreate]<[MonthEnd]) And ([dtFinalClosed]<[MonthEnd]) And (([dtLegalEnd]<[MonthEnd]) Or IsNull([dtLegalEnd])),1,0) AS ProjectUnderConsideration
FROM tblProjectsA;
Now we have a ProjectUnderConsideration Column to sum. Change the query to a totals query:
PARAMETERS MonthEnd DateTime;
SELECT Sum(IIf(([dtCreate]<[MonthEnd]) And ([dtFinalClosed]<[MonthEnd]) And (([dtLegalEnd]<[MonthEnd]) Or IsNull([dtLegalEnd])),1,0)) AS ProjectUnderConsideration
FROM tblProjectsA;

How do I subtract two declared variables in MYSQL

The question I am working on is as follows:
What is the difference in the amount received for each month of 2004 compared to 2003?
This is what I have so far,
SELECT #2003 = (SELECT sum(amount) FROM Payments, Orders
WHERE YEAR(orderDate) = 2003
AND Payments.customerNumber = Orders.customerNumber
GROUP BY MONTH(orderDate));
SELECT #2004 = (SELECT sum(amount) FROM Payments, Orders
WHERE YEAR(orderDate) = 2004
AND Payments.customerNumber = Orders.customerNumber
GROUP BY MONTH(orderDate));
SELECT MONTH(orderDate), (#2004 - #2003) AS Diff
FROM Payments, Orders
WHERE Orders.customerNumber = Payments.customerNumber
Group By MONTH(orderDate);
In the output I am getting the months but for Diff I am getting NULL please help. Thanks
I cannot test this because I don't have your tables, but try something like this:
SELECT a.orderMonth, (a.orderTotal - b.orderTotal ) AS Diff
FROM
(SELECT MONTH(orderDate) as orderMonth,sum(amount) as orderTotal
FROM Payments, Orders
WHERE YEAR(orderDate) = 2004
AND Payments.customerNumber = Orders.customerNumber
GROUP BY MONTH(orderDate)) as a,
(SELECT MONTH(orderDate) as orderMonth,sum(amount) as orderTotal FROM Payments, Orders
WHERE YEAR(orderDate) = 2003
AND Payments.customerNumber = Orders.customerNumber
GROUP BY MONTH(orderDate)) as b
WHERE a.orderMonth=b.orderMonth
Q: How do I subtract two declared variables in MySQL.
A: You'd first have to DECLARE them. In the context of a MySQL stored program. But those variable names wouldn't begin with an at sign character. Variable names that start with an at sign # character are user-defined variables. And there is no DECLARE statement for them, we can't declare them to be a particular type.
To subtract them within a SQL statement
SELECT #foo - #bar AS diff
Note that MySQL user-defined variables are scalar values.
Assignment of a value to a user-defined variable in a SELECT statement is done with the Pascal style assignment operator :=. In an expression in a SELECT statement, the equals sign is an equality comparison operator.
As a simple example of how to assign a value in a SQL SELECT statement
SELECT #foo := '123.45' ;
In the OP queries, there's no assignment being done. The equals sign is a comparison, of the scalar value to the return from a subquery. Are those first statements actually running without throwing an error?
User-defined variables are probably not necessary to solve this problem.
You want to return how many rows? Sounds like you want one for each month. We'll assume that by "year" we're referring to a calendar year, as in January through December. (We might want to check that assumption. Just so we don't find out way too late, that what was meant was the "fiscal year", running from July through June, or something.)
How can we get a list of months? Looks like you've got a start. We can use a GROUP BY or a DISTINCT.
The question was... "What is the difference in the amount received ... "
So, we want amount received. Would that be the amount of payments we received? Or the amount of orders that we received? (Are we taking orders and receiving payments? Or are we placing orders and making payments?)
When I think of "amount received", I'm thinking in terms of income.
Given the only two tables that we see, I'm thinking we're filling orders and receiving payments. (I probably want to check that, so when I'm done, I'm not told... "oh, we meant the number of orders we received" and/or "the payments table is the payments we made, the 'amount we received' is in some other table"
We're going to assume that there's a column that identifies the "date" that a payment was received, and that the datatype of that column is DATE (or DATETIME or TIMESTAMP), some type that we can reliably determine what "month" a payment was received in.
To get a list of months that we received payments in, in 2003...
SELECT MONTH(p.payment_received_date)
FROM payment_received p
WHERE p.payment_received_date >= '2003-01-01'
AND p.payment_received_date < '2004-01-01'
GROUP BY MONTH(p.payment_received_date)
ORDER BY MONTH(p.payment_received_date)
That should get us twelve rows. Unless we didn't receive any payments in a given month. Then we might only get 11 rows. Or 10. Or, if we didn't receive any payments in all of 2003, we won't get any rows back.
For performance, we want to have our predicates (conditions in the WHERE clause0 reference bare columns. With an appropriate index available, MySQL will make effective use of an index range scan operation. If we wrap the columns in a function, e.g.
WHERE YEAR(p.payment_received_date) = 2003
With that, we will be forcing MySQL to evaluate that function on every flipping row in the table, and then compare the return from the function to the literal. We prefer not do do that, and reference bare columns in predicates (conditions in the WHERE clause).
We could repeat the same query to get the payments received in 2004. All we need to do is change the date literals.
Or, we could get all the rows in 2003 and 2004 all together, and collapse that into a list of distinct months.
We can use conditional aggregation. Since we're using calendar years, I'll use the YEAR() shortcut (rather than a range check). Here, we're not as concerned with using a bare column inside the expression.
SELECT MONTH(p.payment_received_date) AS `mm`
, MAX(MONTHNAME(p.payment_received_date)) AS `month`
, SUM(IF(YEAR(p.payment_received_date)=2004,p.payment_amount,0)) AS `2004_month_total`
, SUM(IF(YEAR(p.payment_received_date)=2003,p.payment_amount,0)) AS `2003_month_total`
, SUM(IF(YEAR(p.payment_received_date)=2004,p.payment_amount,0))
- SUM(IF(YEAR(p.payment_received_date)=2003,p.payment_amount,0)) AS `2004_2003_diff`
FROM payment_received p
WHERE p.payment_received_date >= '2003-01-01'
AND p.payment_received_date < '2005-01-01'
GROUP
BY MONTH(p.payment_received_date)
ORDER
BY MONTH(p.payment_received_date)
If this is a homework problem, I strongly recommend you work on this problem yourself. There are other query patterns that will return an equivalent result.
I think this is the problem:
In #2003 and #2004, you select only the sum. And even if you group by the month you still select one column i.e. each row does not say what month it is select for. So when you try to subtract SQL asks which row in #2003 should be subtracted from #2004.
So I think the solution is to select the month with the sum and do the subtract later based on the month.

Exclude zero from average result

I wish to get the 12 week average of sales by day name (IE 12 weeks worth of Mondays...)
but I want to not have the zero values that may occur due to a store closure.Example of 12 Weeks with Zero's
I wrote a script to try exclude the Zero's
select
de.[Restaurant Name]
,dd.[DayNameOfWeek]
,dd.[FinancialWC]
,AVG([Net]) OVER (PARTITION BY dw.[RedCatID], dd.DayNameOfWeek
ORDER BY dw.[RedCatID], dd.[FullDate] ROWS 11 PRECEDING ) as [12 Week]
from Daily_Sales_Summary dw
inner join Restaurant_View de on de.RedCatID = dw.[RedCatID]
inner join DimDate dd on dd.[DateKey] = dw.[DateKey]
where [net] <> '0'
group by de.[Restaurant Name]
,dw.[RedCatID]
,dd.[DayNameOfWeek]
,dd.[FullDate]
,dd.[FinancialWC],[Net]
order by [Restaurant Name] asc
This did give me the averages I wanted but produced no results for the days with a zero value
Query Results showing missing dates
How would I go about doing this without missing the weeks with zero nulls?
I am happy to have it go back an extra week if a zero is present instead of excluding it if that is a simpler solution..
You need to be a little creative here to include rows but not count them in average. Try the code below and see if it works. I haven't tested it.
Basically, what is does is redefines the denominator of calculation to give a count of rows where [NET] <> 0
EDIT: Found a simpler solution than what i originally posted
select
de.[Restaurant Name]
,dd.[DayNameOfWeek]
,dd.[FinancialWC]
,avg(nullif([Net],0)) OVER (PARTITION BY dw.[RedCatID], dd.DayNameOfWeek
ORDER BY dw.[RedCatID], dd.[FullDate] ROWS 11 PRECEDING )
as [12 Week]
from Daily_Sales_Summary dw
inner join Restaurant_View de on de.RedCatID = dw.[RedCatID]
inner join DimDate dd on dd.[DateKey] = dw.[DateKey]
group by de.[Restaurant Name]
,dw.[RedCatID]
,dd.[DayNameOfWeek]
,dd.[FullDate]
,dd.[FinancialWC],[Net]
order by [Restaurant Name] asc

Query by month from date field

I have a set of Access d/b's grouped already by year. within a given year, I have a field caleld REPORTDATE which is a standard mm/dd/yyyy field. However, I need to produce queries that return data by the month. For example, I just want to see records for Jan, recs for Feb, Recs for March, etc., so that I can sum them and work wwith thm.
Do I use an expression in the query design view Criteria field?
Thanks in advance.
I just want to see records for Jan, recs for Feb, Recs for March, etc., so that I can sum them and work wwith thm.
You can do all of that in one sql statement:
select month(reportdate), sum( the column you wish to sum )
from tablename
group by month(reportdate);
BUT WAIT THERE'S MORE!
Further say that there are several salepersons selling stuff, and you wish to show each salesperson's sales by month
select month(reportdate), salesperson, sum( the column you wish to sum )
from tablename
group by month(reportdate), salesperson;
That shows the sum per month per salesperson.
You know the Germans always make good stuff!
What it you wanted to see the same sums, but rtaher than comparing salespeople against each other in each month, you wanted to compare, for each salesperson, how they did from one month to another?
Just reverse the order of the group by:
select month(reportdate), saleperson, sum( the column you wish to sum )
from tablename
group by salesperson, month(reportdate);
Tacos, Fettuccini, Linguini, Martini, Bikini, you're gonna love my nuts!
The power of SQL! As seen on TV! Order now!
"select month(reportdate), sum( the column you wish to sum )from tablenamegroup by month(reportdate);" THIS IS VERY HELPFUL, THANK YOU. AND YOU ARE HILARIOUS. HOWEVER, can you clarify for me where the heck this code goes?! In the expresison Builder or what? Thank you SO much. – rick (19 mins ago)
In Access, I think from the graphical Query Builder thing's menu, select edit|SQL, and just type. And never go back to graphical!
You're a hard-charging forward-thinking entrepreneurially-minded man on the move! This is not your father's Oldsmobile! You wouldn't use an on-screen keyboard to type a document, dragging and dropping letters on the page, would you?! So why do that to build a SQL Query? Get into SQL! AS SEEN ON TV! All the cool kids and hep cats are doin' it! Order NOW!
You can use format, for example:
Format([REPORTDATE],"mmm yy")
Or Month:
SELECT * FROM Table WHERE Month([REPORTDATE]) = 10
An outline of query that may suit, paste this into the SQL view of
the query design window, changing table to the name of your table:
SELECT Format([REPORTDATE],"yyyy mm"), Count([ReportDate])
FROM Table
GROUP BY Format([REPORTDATE],"yyyy mm")
I wouldn't do this in the report's recordsource. I'd make the recordsource a regular SELECT statement and use the report's sorting/grouping. If you group on a date field (one that is really date type), you get the choice to GROUP ON:
Each Value (default)
Year
Qtr
Month
Week
Day
Hour
Minute
I think this is faster than a GROUP BY on a function, but someone who was interested should actually try it.
Certainly if your SELECT with GROUP BY has no WHERE clause, it's going to be a lot more efficient if you run the report with filtered values.