Average score of reviewers from sql table - sql

Below is my query giving me result in sum of corresponding value. How can I calculate average here for each column expect Id?
Select
count(StoreId) as TotalReview,
sum(Case OnTimeDelivery when 'Within Time' then 1 else 0 end) as OnTimeDeliveryWithinTime,
sum(Case OnTimeDelivery when 'Little Delay' then 1 else 0 end) as OnTimeDeliveryLittleDelay,
sum(Case OnTimeDelivery when 'Excess Delay' then 1 else 0 end) as OnTimeDeliveryExcessDelay,
from
StoreReviews
where
StoreId = 1

You need to use the GROUP BY clause
SELECT storeId, COUNT(ontimedelivery), AVG(<column>)
FROM storereviews
WHERE storeid=1
GROUP BY ontimedelivery

You could get the SUM for each store based on your own query but you have to add GROUP BY like:
SELECT Storeid, COUNT(StoreId) as TotalReview,
SUM(Case OnTimeDelivery WHEN 'Within Time' THEN 1 ELSE 0 END) as OnTimeDeliveryWithinTime,
SUM(Case OnTimeDelivery WHEN 'Little Delay' THEN 1 ELSE 0 END) as OnTimeDeliveryLittleDelay,
SUM(Case OnTimeDelivery WHEN 'Excess Delay' THEN 1 ELSE 0 END) as OnTimeDeliveryExcessDelay
FROM StoreReviews
GROUP BY Storeid
Now, if you want to get the Average not for each store but for all stores and based on OnTimeDelivery whether Within Time or Little Delay or Excess Delay you could use AVG like this:
SELECT CONVERT(Decimal(5,2),AVG(CAST(TotalReview as float))) as AvgTotal, CONVERT(Decimal(5,2),AVG(CAST(OnTimeDeliveryWithinTime as float))) as AvgWithinTime, CONVERT(Decimal(5,2),AVG(CAST(OnTimeDeliveryLittleDelay as float))) as AvgLittleDelay, CONVERT(Decimal(5,2),AVG(CAST(OnTimeDeliveryExcessDelay as float))) as AvgExcessDelay
FROM (
SELECT Storeid, COUNT(StoreId) as TotalReview,
SUM(Case OnTimeDelivery WHEN 'Within Time' THEN 1 ELSE 0 END) as OnTimeDeliveryWithinTime,
SUM(Case OnTimeDelivery WHEN 'Little Delay' THEN 1 ELSE 0 END) as OnTimeDeliveryLittleDelay,
SUM(Case OnTimeDelivery WHEN 'Excess Delay' THEN 1 ELSE 0 END) as OnTimeDeliveryExcessDelay
FROM StoreReviews
GROUP BY Storeid
) StoreAverages
See my Fiddle Demo

Related

How to correct error when aggregating from subquery

I have a query that looks like this:
SELECT store_id,
(CASE WHEN txns_A>0 AND txns_B=0 THEN 'A Only' WHEN txns_A=0 AND txns_B>0 THEN 'B Only' END) A_B_indicator,
sum(1) cnt_customers,
sum(spend_A+spend_B)/sum(txns_A+txns_B) avg_receipt
FROM(
SELECT store_id, cust_id
SUM(CASE WHEN A_B_indicator='A' THEN spend else 0 end) spend_A,
SUM(CASE WHEN A_B_indicator='B' THEN spend else 0 end) spend_B,
SUM(CASE WHEN A_B_indicator='A' THEN spend else 0 end) txns_A,
SUM(CASE WHEN A_B_indicator='B' THEN spend else 0 end) txns_B
FROM table1
GROUP BY store_id, cust_id
) table2;
However, this generates an error because store_id is not in a GROUP BY clause. When I rewrite the query to include a GROUP BY store_id clause, it complains that the aggregate columns are not in the Group By. However, if I add them by rewriting the Group By to be Group BY 1,2,3,4, this also generates an error (Not yet supported place for UDAF Sum).
How can I rewrite this query to be error-free?
You can write this as:
SELECT store_id,
(CASE WHEN SUM(txns_A) > 0 AND SUM(txns_B) = 0 THEN 'A Only'
WHEN SUM(txns_A) = 0 AND SUM(txns_B) > 0 THEN 'B Only'
END) as A_B_indicator,
COUNT(*) as cnt_customers,
SUM(spend_A+spend_B)/sum(txns_A+txns_B) as avg_receipt
FROM (SELECT store_id, cust_id
SUM(CASE WHEN A_B_indicator='A' THEN spend else 0 end) as spend_A,
SUM(CASE WHEN A_B_indicator='B' THEN spend else 0 end) as spend_B,
SUM(CASE WHEN A_B_indicator='A' THEN spend else 0 end) as txns_A,
SUM(CASE WHEN A_B_indicator='B' THEN spend else 0 end) as txns_B
FROM table1
GROUP BY store_id, cust_id
) table2
GROUP BY store_id;

Group by in sql for two conditions

I have this table
SELECT
[WeldStatus]
,PackageId
FROM [SPMS2].[dbo].[JointHistory]
How can I group by this query to calculate total testpackage and total accept and total remain?
For example for packageid=6030 I need this:
packageid total accept remain
6030 4 3 1
Use CASE and Group By
SELECT
PackageId,
count(*) as total,
sum(case [WeldStatus] when 'Accept' then 1 end) as accept,
sum(case [WeldStatus] when 'accept' then 0 else 1 end) as remain
FROM [SPMS2].[dbo].[JointHistory]
group by PackageId;
SELECT
packageid
,count(*) as 'total'
,sum(case when weldstatus = 'Accept' then 1 else 0 end) as 'accept'
,sum(case when weldstatus is null then 1 else 0 end) as 'remain'
FROM [SPMS2].[dbo].[JointHistory]
group by packageid
"sum(case when..." has saved me so many times. NULLs can be a pain but the case when saves you.
You can use CASE expression with in your aggregation to achieve your desired output.
SELECT
PackageId,
SUM (CASE WHEN WeldStatus = 'Accept' THEN 1 ELSE 0 END) AS AcceptCount,
SUM (CASE WHEN WeldStatus IS NULL THEN 1 ELSE 0 END) AS RemainCount,
COUNT (*) AS Total
FROM [SPMS2].[dbo].[JointHistory]
GROUP BY PackageId
select packageid, SUM(TOTAL), SUM(ACCEPT), SUM(REMAIN) from (
select packageid, 1 as TOTAL,
case
when WeldStatus='Accept' then 1 else 0
END as ACCEPT,
case
when WeldStatus IS NULL then 1 else 0
END as REMAIN
from JointHistory
) group by packageid
If WeldStatus only takes on the values of 'Accept' or NULL, then a simple method is:
SELECT PackageId, count(*) as total,
count(WeldStatus) as accept,
count(*) - count(WeldStatus) as remain
FROM [SPMS2].[dbo].[JointHistory] jh
GROUP BY PackageId;
I'm the first to admit that this relies on the assumption of having a single value or NULL.
SELECT PackageId,
COUNT(*) AS total,
SUM(CASE WHEN [WeldStatus] = 'Accept' THEN 1 END) AS accept,
SUM(CASE WHEN ISNULL([WeldStatus],'') = '' THEN 1 ELSE 0 END) AS remain
FROM [SPMS2].[dbo].[JointHistory]
group by PackageId;

Using multiple sum case lines in query

This code does exactly what I need it to do for the desired months. Basically provides Numerator and Denominator.
SUM(CASE WHEN smsdss.c_cfv_pas_fct_pt_acct_vst_all.vst_end_date BETWEEN '2013-01-01' and '2013-01-31' THEN 1 ELSE 0 END) AS Total_Jan13,
SUM(CASE WHEN smsdss.c_cfv_pas_fct_pt_acct_vst_all.vst_end_date BETWEEN '2013-01-01' and '2013-01-31' and [ind_ra_cfvmc_00-30] = 'YES' THEN 1 ELSE 0 END) AS RA_Jan13,
SUM(CASE WHEN smsdss.c_cfv_pas_fct_pt_acct_vst_all.vst_end_date BETWEEN '2013-02-01' and '2013-02-28' THEN 1 ELSE 0 END) AS Total_Feb13,
SUM(CASE WHEN smsdss.c_cfv_pas_fct_pt_acct_vst_all.vst_end_date BETWEEN '2013-02-01' and '2013-02-28' and [ind_ra_cfvmc_00-30] = 'YES' THEN 1 ELSE 0 END) AS RA_Feb13,
SUM(CASE WHEN smsdss.c_cfv_pas_fct_pt_acct_vst_all.vst_end_date BETWEEN '2013-03-01' and '2013-03-31' THEN 1 ELSE 0 END) AS Total_Mar13,
It can get pretty tedious when you have multiple months...is there a more efficient way of performing this calculation?
THanks!
You could group them by the year and month in a sub-select and then manipulate that:
SELECT DATEPART(year, smsdss.c_cfv_pas_fct_pt_acct_vst_all.vst_end_date) AS TotalYear,
DATEPART(month, smsdss.c_cfv_pas_fct_pt_acct_vst_all.vst_end_date) AS TotalMonth,
COUNT(*) AS Total
FROM [table]
GROUP BY DATEPART(year, smsdss.c_cfv_pas_fct_pt_acct_vst_all.vst_end_date),
DATEPART(month, smsdss.c_cfv_pas_fct_pt_acct_vst_all.vst_end_date)
and that would give you the totals by month, without having to specify the months beforehand.

Multiple Sums off Same Column

I need this select query to return the sum of the same column based on different where clauses. Basically just looking for a way to merge these multiple select queries. Please see below. Any help is very much appreciated!
DECLARE #prEndDate smalldatetime
SET #prEndDate='2014-01-05'
SELECT Employee, SUM(Amount) as Deduction
FROM bPRDT
WHERE PREndDate=#prEndDate
AND EDLCode=100 AND EDLType='D'
GROUP BY Employee
SELECT Employee, SUM(Amount) as DeductionPlus
FROM bPRDT
WHERE PREndDate=#prEndDate
AND EDLCode=101 AND EDLType='D'
GROUP BY Employee
SELECT Employee, SUM(Amount) as Match
FROM bPRDT
WHERE PREndDate=#prEndDate
AND EDLCode=600 AND EDLType='L'
GROUP BY Employee
SELECT Employee, SUM(Amount) as MatchPlus
FROM bPRDT
WHERE PREndDate=#prEndDate
AND EDLCode=601 AND EDLType='L'
GROUP BY Employee
Finally fixed. Here's what it ended up being:
DECLARE #prEndDate smalldatetime
SET #prEndDate ='2013-12-29'
SELECT
REPLACE(c.SSN,'-',''),
SUM(CASE WHEN a.EDLType='D' AND a.Amount > 0 AND (a.EDLCode=100 OR a.EDLCode=101) THEN a.Amount ELSE 0 END) AS Deferral,
SUM(CASE WHEN a.EDLType='L' AND a.Amount > 0 AND (a.EDLCode=600 OR a.EDLCode=601) THEN a.Amount ELSE 0 END) AS EmployerMatch,
SUM(CASE WHEN a.EDLType='D' AND a.Amount > 0 AND (a.EDLCode=100 OR a.EDLCode=101) THEN a.SubjectAmt ELSE 0 END) AS Compensation415,
SUM(CASE WHEN a.EDLType='D' AND a.Amount > 0 AND (a.EDLCode=100 OR a.EDLCode=101) THEN a.SubjectAmt ELSE 0 END) AS PlanFullYearCompensation,
SUM(CASE WHEN a.EDLType='E' AND a.Amount > 0 AND (a.EDLCode=1 OR a.EDLCode=2 OR a.EDLCode=3) THEN a.Hours ELSE 0 END) AS PlanHours
FROM bPRDT a
JOIN (SELECT DISTINCT SSN, Employee FROM bPREH) c ON a.Employee=c.Employee
WHERE a.PREndDate=#prEndDate
GROUP BY c.SSN
ORDER BY Deferral DESC, c.SSN ASC
You could use UNION or CASE WHEN clauses.
SELECT
Employee,
SUM(CASE WHEN EDLCode=100 AND EDLType='D' THEN Amount ELSE 0 END) as Deduction,
SUM(CASE WHEN EDLCode=101 AND EDLType='D' THEN Amount ELSE 0 END) as DeductionPlus
SUM(CASE WHEN EDLCode=600 AND EDLType='L' THEN Amount ELSE 0 END) as Match
SUM(CASE WHEN EDLCode=601 AND EDLType='L' THEN Amount ELSE 0 END) as MatchPlus
FROM bPRDT
WHERE PREndDate=#prEndDate
GROUP BY Employee
You can move the condition out of the WHERE clause and in to a CASE statement, so you only sum the rows that interest you:
DECLARE #prEndDate smalldatetime
SET #prEndDate='2014-01-05'
SELECT Employee,
SUM(CASE WHEN EDLCode=100 AND EDLType='D' THEN amount ELSE 0 END)
AS Deduction,
SUM(CASE WHEN EDLCode=101 AND EDLType='D' THEN amount ELSE 0 END)
AS DeductionPlus,
SUM(CASE WHEN EDLCode=600 AND EDLType='L' THEN amount ELSE 0 END)
AS Match,
SUM(CASE WHEN EDLCode=601 AND EDLType='L' THEN amount ELSE 0 END)
AS MatchPlus
FROM bPRDT
WHERE PREndDate = #prEndDate
GROUP BY Employee
Group by Employee,EDLCode,EDLType instead of just Employee.

How come I am getting the same total values of 2 different columns

I need someone to correct the statement below please. Thank you in advance.
SELECT CATEGORY
--WHAT PERIOD?
,'P3' AS PERIOD
,'2013' AS FISCALYEAR
,COUNT(CASE SecurityLayer WHEN 'dblayer' THEN SecurityLayer ELSE '' END) DB_SEC_COUNT
,COUNT(CASE SecurityLayer WHEN 'Applayer' THEN SecurityLayer ELSE '' END) APP_SEC_COUNT
FROM [db_eCAM].[dbo].[tbl_SecChecks]
GROUP BY CATEGORY
Are you trying to return the # of times each of those things matches? Then use
SELECT CATEGORY
--WHAT PERIOD?
,'P3' AS PERIOD
,'2013' AS FISCALYEAR
,SUM(CASE SecurityLayer WHEN 'dblayer' then 1 else 0 end) AS DB_SEC_COUNT
,SUM(CASE SecurityLayer WHEN 'Applayer' then 1 else 0 end) AS APP_SEC_COUNT
FROM [db_eCAM].[dbo].[tbl_SecChecks]
GROUP BY CATEGORY
Try that.
Instead of counting the columns try summing it (otherwise each row will still be counted regardless of its value):
SELECT CATEGORY
--WHAT PERIOD?
,'P3' AS PERIOD
,'2013' AS FISCALYEAR
,SUM(CASE SecurityLayer WHEN 'dblayer' THEN 1 ELSE 0 END) DB_SEC_COUNT
,SUM(CASE SecurityLayer WHEN 'Applayer' THEN 1 ELSE 0 END) APP_SEC_COUNT
FROM [db_eCAM].[dbo].[tbl_SecChecks]
GROUP BY CATEGORY