Compare value in each row to average of the column (SQL) - sql

I am trying to create a view where the score for each row is compared to the average for that column, so that I can easily identify records by their rough "grade". Simplified code:
select recordID,
case when table.ColumnA>avg(all table.ColumnA) then 'Hard' else 'Easy' end as Difficulty,
from table
group by recordID, ColumnA
I've tried various combinations of this and the case formula keeps defaulting to 'else', which on investigation seems to be that every calculated value is coming out as 0, as both the row value and average value are being deemed the same.
I have a feeling the answer has something to do with Rollup, either on this table or the source table, but the syntax required is beyond me.
Anyone?

You want a window function:
select recordID,
(case when table.ColumnA > avg(table.ColumnA) over ()
then 'Hard' else 'Easy'
end) as Difficulty
from table;

Related

Why does a CASE WHEN give me a different result to a WHERE with the same condition?

I'm trying to use a case when and a pivot to filter some data, but get a result of a total count of 0, however, when I use the same condition in a where statement I get a result that's more what i expected.
SELECT * FROM(SELECT FYEAR,
CASE WHEN (DIAG_3_01 IN ('E10','E11','E12','E13','E14','O24') OR DIAG_4_01 IN ('E232','N251','P702')) AND (OPERTN_3_01 IN ('N26','P22','X07','X09','X10','X11') OR OPERTN_4_01 IN ('Q011','X215','X216','X273','X121')) THEN 'a'
ELSE 'Other' END AS 'Procs',
(FCE)
FROM database
) AS a
PIVOT(COUNT(FCE) FOR [Procs] IN ([a])) AS p;
So this results in a table with column name a and a row value of 0, whereas this code results in a total of about 4000:
SELECT COUNT(FCE)
FROM database
WHERE (DIAG_3_01 IN ('E10','E11','E12','E13','E14','O24') OR DIAG_4_01 IN ('E232','N251','P702')) AND (OPERTN_3_01 IN ('N26','P22','X07','X09','X10','X11') OR OPERTN_4_01 IN ('Q011','X215','X216','X273','X121'));
Unfortunately I cant share the database contents, but would appreciate any insight as to why this might be happening.
The CASE statement is like an If-statement, which only returns the very first value it founds that meets the criteria. You can also check multiple cases with WHEN and if no criteria are met, then the query will show whatever is in the ELSE statement.
The WHERE clause is just filtering the result, meaning it tell the query which records should not be ignored.

Getting another column from same row which has first non-null value in column

I have a SQL table like this and I want to find the average adjusted amt for products partitioned by store_id that looks like this
Here, I need to compute the adj_amt which is the product of the previous two columns.
For this, I need to fill the nulls in the avg_quantity with the first non_null value in the partition. The query I use is below.
select
CASE WHEN av_quantity is null then
# the boolen here is for non-null values
first_value(av_quantity, True) over (partition by store_no order by product_id
range between current row and unbounded following
)
else av_quantity
end as adj_av_quantity
I'm having trouble with the SQL required to get the adjusted cost, since its not pulling the first non_null value for factor but still fetches it based on the same row for the adj_av_quantity. any thoughts on how I could do this?
FYI I've simplified the data here. The actual dataset is pretty huge (> 125 million rows with 800+ columns) so I won't be able to use joins and have to do this via window functions. I'm using spark-sql

How to Sum two columns meeting certain conditions

What I want to do is basically merge the two highlighted code, so that the end result is it using this SUM formula for only the items matching the LIKE criteria (under WHERE) - so that I am still able to pull GameDescriptions that do not include the LIKE criteria. Hope that makes sense... enter image description here
I think you just need to replace that part of the WHERE statement with a case statement in the SUM, like this:
SELECT
SUM(CASE WHEN GameDescription LIKE '5R25L%' THEN NetRevenue
ELSE 0 END) / COUNT(DISTINCT AccountingDate)
AS 'ES Created TheoWPU'
FROM Prime.dbo.PivotData

Return NULL instead of 0 when using COUNT(column) SQL Server

I have query which running fine and its doing two types of work, COUNT and SUM.
Something like
select
id,
Count (contracts) as countcontracts,
count(something1),
count(something1),
count(something1),
sum(cost) as sumCost
from
table
group by
id
My problem is: if there is no contract for a given ID, it will return 0 for COUNT and Null for SUM. I want to see null instead of 0
I was thinking about case when Count (contracts) = 0 then null else Count (contracts) end but I don't want to do it this way because I have more than 12 count positions in query and its prepossessing big amount of records so I think it may slow down query performance.
Is there any other ways to replace 0 with NULL?
Try this:
select NULLIF ( Count(something) , 0)
Here are three methods:
1. (case when count(contracts) > 0 then count(contracts) end) as countcontracts
2. sum(case when contracts is not null then 1 end) as countcontracts
3. nullif(count(contracts), 0)
All three of these require writing more complicated expressions. However, this really isn't that difficult. Just copy the line multiple times, and change the name of the variable on each one. Or, take the current query, put it into a spreadsheet and use spreadsheet functions to make the transformation. Then copy the function down. (Spreadsheets are really good code generators for repeated lines of code.)

How do I make this query fast? It reaches time out anytime I run it in the SQL Server database

SELECT firstpartno, nOccurrence, nMale, nFemale, COUNT(nMale) / CAST
((SELECT SUM(nOccurrence) AS Expr1
FROM (SELECT COUNT(dbo.vw_Tally1.nMale) AS nOccurrence
FROM dbo.vw_Split4) AS SumTally) AS decimal) AS nMProportion, COUNT(nFemale) / CAST
((SELECT SUM(nOccurrence) AS Expr1
FROM (SELECT COUNT(dbo.vw_Tally1.nFemale) AS nOccurrence
FROM dbo.vw_Split4 AS vw_Split4_1) AS SumTally_1) AS decimal) AS nFProportion
FROM dbo.vw_Tally1
GROUP BY firstpartno, nOccurrence, nMale, nFemale
If i understood your question here's the solution for you :
SELECT
firstpartno
,nOccurrence
,nMale
,nFemale
,CASE WHEN SUM_nOccurrence.SUM_nOccurrenceMale = 0
THEN 0
ELSE COUNT(nMale)/SUM_nOccurrence.SUM_nOccurrenceMale
END AS nMProportion
,CASE WHEN SUM_nOccurrence.nOccurrenceFemale = 0
THEN 0
ELSE COUNT(nFemale)/SUM_nOccurrence.nOccurrenceFemale
END AS nFProportion
FROM
dbo.vw_Tally1
LEFT JOIN
(SELECT
CAST(SUM(nOccurrenceMale)AS decimal) AS SUM_nOccurrenceMale
,CAST(SUM(nOccurrenceFemale)AS decimal) AS SUM_nOccurrenceFemale
FROM (SELECT
COUNT(dbo.vw_Tally1.nMale) AS nOccurrenceMale
,COUNT(dbo.vw_Tally1.nFemale) AS nOccurrenceFemale
FROM dbo.vw_Split4 ) AS SumTally) SUM_nOccurrence
ON 1=1
GROUP BY
firstpartno
,nOccurrence
,nMale
,nFemale
I hope this will help you
Good Luck :)
The query looks dubious to say the least. You select all records of table vw_Tally1. For each of these records you do the following:
select COUNT(vw_Tally1.nMale) from table vw_Split4. This is COUNT(*) of vw_Split4 when vw_Tally1.nMale is not null, otherwise it is null.
Then you sum this value. Which makes no sense, as the sum of a value is the value itself.
You do the same for nFemale.
At last you group by (firstpartno, nOccurrence, nMale, nFemale) and use the values found so strangly to calculate something. As you don't aggregate the found values, you get a random match per group. I.e. the dbms takes one of the matching records. As nMale and nFemale are grouping columns, the values are constant for all records of the group. So no big problem, but a lot of useless work.
So to speed this up, first think of what you want to select actually. This looks like to become a very simple select statement in the end. We can help you, if you tell us what your tables contain, what result set you are after, what does nMale and nFemale stand for, and what are the primary keys or unique columns of the tables involved.