STDEVP for calculated fields - sql

I have a table that looks like this:
ID CHANNEL VENDOR num_PERIOD SALES.A SALES.B
000001 Business Shop 1 40 30
000001 Business Shop 2 60 20
000001 Business Shop 3 NULL 30
With many combinations of ID, CHANNEL and VENDOR, and sales records for each of them over time (num_PERIOD).
I want to get the average Standard Deviation of a new field, which returns the sum of SALES.A + SALES.B sum(IS.NULL(SALES.A,0) + ISNULL(SALES.B,0)).
The problem I have is that STDEVP seem to fail with calculated fields, and the result that returns is invalid.
I have been trying with:
select ID, CHANNEL, VENDOR, stdevp(sum(isnull(SALES.A,0) + ISNULL(QSALES.B,0))) OVER (PARTITION BY ID, CHANNEL, VENDOR) as STDEV_SALES
FROM TABLE
GROUP BY ID, CHANNEL, VENDOR
However, the results I'm obtaning are always 0 or NULL.
What I want to obtain is the Average Standard Deviation of each ID, CHANNEL and VENDOR over time (num_PERIOD).
Can someone find an approximation for this please?

Your query doesn't match the sample data.
I can see the problem, though. The SUM() are calculating a single value for each group, and then you are taking the standard deviation of that value. Because you cannot nest aggregation functions, you have turned it into a window function.
Get rid of the sum(). The following should work in SQL Server:
SELECT ID, CHANNEL, VENDOR,
STDEVP(COALESCE(SALES.A, 0) + COALESCE(QSALES.B, 0)) as STDEV_SALES
FROM SALES . . .
QSALES
GROUP BY ID, CHANNEL, VENDOR;
I would also return the COUNT(*) . . . the standard deviation doesn't make sense if you have fewer than 3 rows. (Okay, it is defined for two values, but not very useful.)

Related

Calculating the percentage of different types of customer feedback in each quarter

The problem statement is: I have a table (order_t) which has customer feedback (one column) and quarter number (as another column).
Using a CTE, I need to calculate the percentage of number of customer feedback in each category as well as the total number of customer feedback in each quarter.
After this happens, I need the percentage of different types of customer feedback (like good, bad, ok, very good, very bad) but using CTE.
How can I solve this statement?
I try to solve customer feedback as
WITH total_feedback AS
(
SELECT *
COUNT(CUSTOMER_FEEDBACK), QUARTER NUMBER
FROM
table1
GROUP BY
2
)
But I'm unable to calculate the first half portion, i.e. percentage of different types of customer feedback in each quarter using CTE.
How can I do that?
Find the file of the data
What you could do, and I'll keep the example as close to the code you provided as possible, is the following - using 2 CTE's:
WITH total_feedback AS (
SELECT COUNT(CUSTOMER_FEEDBACK) AS total_feedback, QUARTER_NUMBER
FROM table1
GROUP BY 2
),
category_feedback AS (
SELECT COUNT(CUSTOMER_FEEDBACK) AS feedback_count, CUSTOMER_FEEDBACK, QUARTER_NUMBER
FROM table1
GROUP BY 2, 3
)
SELECT
category_feedback.CUSTOMER_FEEDBACK,
category_feedback.QUARTER_NUMBER,
(feedback_count / total_feedback.total_feedback) * 100 AS feedback_percentage
FROM category_feedback
INNER JOIN total_feedback
ON category_feedback.QUARTER_NUMBER = total_feedback.QUARTER_NUMBER

Group certain rows by a value range

I am trying to group a certain records by its price range. Lets say Customer A bought Product B multiple Times as shown below figure, I want to group them together. The Below customer bought products at different price points like 800,810,830,850 etc. I want to compare each price point against others price points in the tables and see if they can grouped together.
Lets say there are ten price points
800,800,850,820,830,1200,1220,1200,1250,1230.
I want to group numbers which are in 10% of its range. The first 5 numbers 800,800,850,820,830 are in one group and the other numbers are in a different group. How can I achieve this SQL Server?
If I understand correctly, you want one group of:
min + 0.1 * (max - min)
for each customer as a group. Then you want the rest in another group. You can use window functions and arithmetic for this:
select t.*,
(case when price <= 0.1 * max(price) over (partition by customer) + 0.9 * min(price) over (partition by customer)
then 1 else 2
end) as the_group
from t;

MS Access Query to records with same data in different fields in the same row

The title is a bit confusing but I'll explain my problem here:
So i have a database table with millions of lines of spending data broken up into different time fields (period1 - period14). Now what i need to do is write a query that will return the records where the spending in one period is equal to the spending in a different period within the same record. So basically that means if i have a reecord where the spending in period1 is $100 and then the spending in period5 is also $100, it will add that record to a new table. I tried something like the code below but since I'm very new to access it is rather complex/inefficient and also doesn't do what i need it to.
INSERT INTO Contracts
SELECT *
FROM SPENDDETAIL
WHERE (SPENDDETAIL.Period1 = SPENDDETAIL.Period2 OR SPENDDETAIL.Period3 [...] OR SPENDDETAIL.Period14)
AND (SPENDDETAIL.Period1 <> 0 OR SPENDDETAIL.Period2 <> 0 [...] OR SPENDDETAIL.Period14 <> 0);
Any help much appreciated, thanks!
Oh also i know this code snippet would only return the records where the period1 spend equals the spend from any of the other periods it was just a beginning attempt at making the query do what i need it to.
Something along these lines might get you started:
SELECT Id, Value, COUNT(*) FROM
(SELECT Id AS Id, 1 AS Period, Period1 AS Value FROM SPENDDETAIL
UNION ALL
SELECT Id AS Id, 2 AS Period, Period2 AS Value FROM SPENDDETAIL
UNION ALL
SELECT Id AS Id 3 AS Period, Period3 AS Value FROM SPENDDETAIL
etc...) x
GROUP BY Id, Value
HAVING COUNT(*) > 1
Where Id is some unique identifier for each row of the data (assuming there is such a thing).
This will give you a list of Ids and matching values.

understanding group by statements in rails

Given a invoices table like this:
invoice_date customer total
2012/01/01 A 780
2013/05/01 A 3800
2013/12/01 A 1500
2012/07/01 B 15
2013/03/01 B 21
Say that i want both:
the count of invoices of each customer of each year
the sum of the amounts of all the invoices of each customer of each year
the max amount among all the invoices of each customer of each year
That is, in SQL, very easily:
SELECT CUSTOMER, YEAR(invoice_date) as INVOICE_YEAR, MAX(total) AS MAX_TOTAL, SUM(total) AS SUM_AMOUNTS, count(*) AS INVOICES_NUM AS SUM_TOTAL FROM invoices GROUP BY YEAR(invoice_date), CUSTOMER;
(the function to extract the year of a date may be YEAR(date) or something else depending on the database server, on sqllite is strftime('%y', invoice_date))
Ok, i've tryed to translate this in rails/ActiveRecord:
Invoice.count(:group => 'customer')
This works, but how can i get both count and sum and max?
The idea i'm familiar with is that (in SQL) a group by generates the rows (well, to be correct, determines which rows should exist in the result table), and then you pass an arbitrary number of aggregation functions that are applyed on every disaggregate set of rows that are behind a single result row. E.G: group by customer means: one row for Customer A, one row for customer B; then I can pass how many aggregation function i want: count(*), max(total), max(date), min(total) just to list the most common.
Looking at the rails ActiveRecord API it seems that you're supposed to do just one function at a time, because the group is an argument of the count. And if i want a multiple aggregation functions, say max, sum etc?
Second attempt
irb> i = Invoice.select('customer, sum(total)').group('customer')
Invoice Load (0.3ms) SELECT customer, sum(total) AS TOTAL_GROUP FROM "invoices" GROUP BY customer
=> [#, #]
That is: it doesn't give back the field with the sum...
Well it does, it just doesn't get printed out.
Say you query is i = Invoice.select('customer, sum(total) as sum_total').group('customer')
So i is an array(technically it's not an array, but not important here) containing all the result. So i[0].sum_total will give you the sum of the first customer, but of course you should iterate it to get everything you want.

To calculate % in hive query

with the below query i can able to get the approved transaction for per client on per day basis.
select
q1.client_id,
q1.receive_day,
count(q1.client_id) as cnt
from
(select * from sale where response=00) q1
group by
q1.client_id, q1.receive_day
I want to get the approval %, i.e. the approval_per, is 100*(count(client_id)/response), while count(client_id) is the number of clients for the approved transaction.
Response is a count of whole response including all the values (approved and not approved) . I can get the response by select count(response) from sale , but how to make it here for calculating % in the same query is the problem am facing now. I tried out some options as it didn't work , reached user group.
so my expected output format is client_id,receive_day,count(client_id),approval_per.
Any of your help are really appreciated
Thanks & Regards,
dti
You could simply add another subquery which calculates that count. Also for the query you have now it seems unnecessary to have that subquery (q1).
I also make the assumption that you want your percentage should be the percentage of transactions each client is responsible for. I.e. number of transactions for given client divided by number of total transactions.
SELECT
s.client_id,
s.receive_day,
count(s.client_id) as cnt,
100 * (count(s.client_id) / q1.total)
FROM
sale s,
(select count(*) total from sale) q1
WHERE
response = 00
GROUP BY
s.client_id, s.receive_day