Cleaning "SUM" Query - sql

I have a bit of sql code that look similar to this:
select sum(case when latitude = '0' then 1 else 0 end) as count_zero,
sum(case when latitude is NULL then 1 else 0 end) as count_null,
sum((case when latitude = '0' then 1 else 0 end) +
(case when latitude is NULL then 1 else 0 end)
) as total_zero,
count(latitude) as count_not_nulls,
count(*) as total
from sites_database
Is there a "cleaner" way to write this same query. I have tried using the "sum" expression using the column alias, something like:
Sum(count_zero + count_null) as total_null
But this doesn't seem to work for some reason

You could use COUNT instead of SUM:
SELECT
COUNT(CASE WHEN latitude = '0' THEN 1 END) As count_zero,
COUNT(CASE WHEN latitude IS NULL THEN 1 END) AS count_null,
COUNT(CASE WHEN COALESCE(latitude, '0') = '0' THEN 1 END) AS total_zero,
COUNT(latitude) As count_not_nulls,
COUNT(*) as total
FROM sites_database;
Using COUNT here saves a bit of coding, because we don't have to provide an explicit ELSE condition (the default ELSE is NULL, which just isn't counted at all). Also note that for the total_zero conditional sum, I used COALESCE to merge the two counts into just one.

Related

SQL percentage with rows same table with different where condition

I want to do a query like:
select
count(asterisk) where acción='a'/count(asterisk) where acción='b' * 100
from
same_table
grouped by day
but I don't want use subquery, is it possible with joins?
I`m not sure the syntax is correct, but you can use something like this:
SELECT day,
SUM(CASE WHEN "acción" = 'a' THEN 1 ELSE 0 END) AS SUM_A,
SUM(CASE WHEN "acción" = 'b' THEN 1 ELSE 0 END) AS SUM_B,
SUM(CASE WHEN "acción" = 'a' THEN 1 ELSE 0 END) AS SUM_A / SUM(CASE WHEN "acción" = 'b' THEN 1 ELSE 0 END) * 100 AS result
FROM your_table
GROUP BY day
The concept is to actually sum the the values that you need, instead of count.

SQLITE How to Divide two count results in the same query

My current code:
SELECT VENDOR.[VENDOR_NAME], DEVICE.[DEVICE_NAME], DEVICE.[PK_DEVICE],MODELDEVICE.[FK_MODELDEVICE_DEVICE],
COUNT(RESULT.[FK_RESULT_COMMAND]) AS TOTAL_TESTS,
COUNT(case when TYPERESULT.[TYPERESULT_NAME]='ERROR' then 1 else null end) as ERROR,
COUNT(case when TYPERESULT.[TYPERESULT_NAME]='OK' then 1 else null end) as OK,
COUNT(case when TYPERESULT.[TYPERESULT_NAME]='SKIP' then 1 else null end) as SKIP,
COUNT(DISTINCT PK_COMMAND) AS COMMAND_COUNT,
COUNT(DISTINCT RESULT_ORDER) AS RESULT_COUNT
The question is that I need another column with the result of dividing total ERROR results in TOTAL_TESTS results, and I don´t know how to do that
I have a preference for using SUM() in this case, rather than COUNT(). I think you will see why, because the average is easy to calculate as well:
COUNT(*) AS TOTAL_TESTS,
SUM(case when TYPERESULT.[TYPERESULT_NAME] = 'ERROR' then 1 else 0 end) as ERROR,
SUM(case when TYPERESULT.[TYPERESULT_NAME] = 'OK' then 1 else 0 end) as OK,
AVG(case when TYPERESULT.[TYPERESULT_NAME] = 'ERROR' then 1.0 else 0 end) as ERROR,
. . .
Note the use of 1.0. This is because SQLite does integer division, so we need to pass in a non-integer value.
Just divide the 2 columns.
SELECT VENDOR.[VENDOR_NAME], DEVICE.[DEVICE_NAME], DEVICE.[PK_DEVICE],MODELDEVICE.[FK_MODELDEVICE_DEVICE],
COUNT(RESULT.[FK_RESULT_COMMAND]) AS TOTAL_TESTS,
COUNT(CASE WHEN TYPERESULT.[TYPERESULT_NAME] = 'ERROR' THEN 1 ELSE NULL END) AS ERROR,
COUNT(CASE WHEN TYPERESULT.[TYPERESULT_NAME] = 'OK' THEN 1 ELSE NULL END) AS OK,
COUNT(CASE WHEN TYPERESULT.[TYPERESULT_NAME] = 'SKIP' THEN 1 ELSE NULL END) AS SKIP,
COUNT(DISTINCT PK_COMMAND) AS COMMAND_COUNT,
COUNT(DISTINCT RESULT_ORDER) AS RESULT_COUNT,
(COUNT(CASE WHEN TYPERESULT.[TYPERESULT_NAME] = 'ERROR' THEN 1.0 ELSE NULL END))/(COUNT(RESULT.[FK_RESULT_COMMAND])) AS DivColumn

Avoiding a divide by zero error in a case statement

I am getting a divide by zero error in my script.
Can anyone please help.
I am trying to divide two records and one of them has zero in it. I dont want to lose the row, please advise.
select DATEPART(Year,Request_date) as "Year",
DATEPART(Month,Request_date) as "Month",
COUNT([MONTH_OF_SUSPENSION]) as "Request" ,
sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end) as "Paid in 24hrs",
COUNT([MONTH_OF_SUSPENSION])/sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end) as "Achieved"
FROM suspension_br
where REQUEST_STATUS = 'OTHERS'
GROUP BY DATEPART(Year,Request_date),DATEPART(Month,Request_date)
You can introduce a second case to check the result of the sum:
case
when sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end) > 0
then COUNT([MONTH_OF_SUSPENSION])/sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end)
else 0 /* a default value that makes sense to you */
end as "Achieved"
Looking at your code I could assume you are using MSSQL and therefore you could use nullif which returns null if two arguments are equal. So for example your code could look like :
COUNT([MONTH_OF_SUSPENSION])/nullif(sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end),0) as "Achieved"
What it does is if the value of the sum operator is equal 0 then the divisor is turn from zero into null and that will result in the entire equation to become null.
use another case statement to check the result of your sum
select DATEPART(Year,Request_date) as "Year",
DATEPART(Month,Request_date) as "Month",
COUNT([MONTH_OF_SUSPENSION]) as "Request" ,
sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) as "Paid in 24hrs",
case
when sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) = 0 then 'whatever you want in this case'
else COUNT([MONTH_OF_SUSPENSION])/sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) as "Achieved"
FROM suspension_br
where REQUEST_STATUS = 'OTHERS'
GROUP BY DATEPART(Year,Request_date),DATEPART(Month,Request_date)
although this is pretty nasty looking, so you could tidy it up a bit with a sub-select:
select
year,
month,
request,
PaidIn24hrs,
case
when PaidIn24hrs = 0 then 'whatever you want in this case'
else request/PaidIn24hrs
end as "Achieved"
from
(
select DATEPART(Year,Request_date) as "Year",
DATEPART(Month,Request_date) as "Month",
COUNT([MONTH_OF_SUSPENSION]) as "Request" ,
sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) as "PaidIn24hrs"
FROM suspension_br
where REQUEST_STATUS = 'OTHERS'
GROUP BY DATEPART(Year,Request_date),DATEPART(Month,Request_date)
)

select sum statement

I created this select statement I will convert to a view. I need help with this. I need to be able to add the total of Minority that = Yes and No show total on report pages.
select
ps.BidPackage_ID,
ps.Project_ID,
SUM (case ps.Minority when 'Yes' then 1 else 0 end) MinorityTotal,
SUM (case ps.Gender when 'Female' then 1 else 0 end) FemaleTotal,
SUM(case ps.Cleveland_Resident when 1 then 1 else 0 end) ClevelandResidents,
ps.SubContractor
from
PersonnelSummary ps
group by
ps.BidPackage_ID,
ps.Project_ID,
ps.SubContractor
You nearly have it:
...
SUM (case ps.Minority when 'Yes' then 1 else 0 end) AS MinorityYes,
SUM (case ps.Minority when 'No' then 1 else 0 end) AS MinorityNo,
COUNT(*) AS Total,
...
With the Total I'm assuming that every row should be counted. This is what you want if:
The only values that exist in the column are 'Yes' and 'No' or
Values different from 'Yes' and 'No' should also be counted in the total.
You're forcing us to guess what you want. You have a count of the people who said that they were in a minority; do you want a count of the people who said No? Or do you want a count of the number who said 'either "Yes" or "No"' and excluding those who gave 'decline to say' or simply no answer at all?
select
ps.BidPackage_ID,
ps.Project_ID,
SUM (case ps.Minority when 'Yes' then 1 else 0 end) MinorityTotalYes,
SUM (case ps.Minority when 'No' then 1 else 0 end) MinorityTotalNo,
SUM (case ps.Minority when 'Yes' then 1 when 'No' then 1 else 0 end)
AS StatedMinorityTotal,
SUM (case ps.Gender when 'Female' then 1 else 0 end) FemaleTotal,
SUM(case ps.Cleveland_Resident when 1 then 1 else 0 end) ClevelandResidents,
ps.SubContractor
from
PersonnelSummary ps
group by
ps.BidPackage_ID,
ps.Project_ID,
ps.SubContractor

MySQL using calculated return values to calculate other values

Let's say I have a select Statement with the following:
SUM(st.tafPoints/200) as totalFriendReferrals,
SUM(CASE WHEN st.gender = "m" THEN st.tafPoints/200 ELSE 0 END) as maleFriendReferrals,
SUM(CASE WHEN st.gender = "f" THEN st.tafPoints/200 ELSE 0 END) as femaleFriendReferrals
I need to calculate the percentage of maleFriendReferrals based on the totalFriendReferrals. These are both derived (ie, not originally in the list of columns) values. So if I try to do something like:
CONCAT( (maleFriendReferrals/totalFriendReferrals) *100 , '%') as malePercentReferrals
But I get an error:
Unknown column 'maleFriendReferrals' in 'field list' – 1 ms
Is there a way to do this easily? I need to be able to do this within the query itself, and not have to loop through my results to calculate percentages.
You should put the original query to a subquery
SELECT CONCAT( (maleFriendReferrals/totalFriendReferrals) *100 , '%') as malePercentReferrals
FROM
(SELECT
SUM(st.tafPoints/200) as totalFriendReferrals,
SUM(CASE WHEN st.gender = "m" THEN st.tafPoints/200 ELSE 0 END) as maleFriendReferrals,
SUM(CASE WHEN st.gender = "f" THEN st.tafPoints/200 ELSE 0 END) as femaleFriendReferrals
FROM st) AS subquery