CASE Expression returning NULL when with other case statements, returns expected result when alone - sql

When i run this line of code alone i get the expected result of 1:
sum(case when facilityname like '%AT%' then count(status) else 0 end) as AT_all_status
However when i run with multiple case statements together as shown in this example all case statements return NULL:
sum(case when facilityname like '%AT%' then count(status) else 0 end) as AT_all_status,
sum(case when facilityname like '%AT%' and status in ('Current','Approved') then count(status) else 0 end) as AT_approved_current,
sum(case when facilityname like '%CZ%' then count(status) else 0 end) as CZ_all_status,
sum(case when facilityname like '%CZ%' and status in ('Current','Approved') then count(status) else 0 end) as CZ_approved_current,
sum(case when facilityname like '%FGE%' then count(status) else 0 end) as FGE_all_status,
sum(case when facilityname like '%FGE%' and status in ('Current','Approved') then count(status) else 0 end) as FGE_approved_current,
sum(case when facilityname like '%FRA%' then count(status) else 0 end) as FRA_all_status,
sum(case when facilityname like '%FRA%' and status in ('Current','Approved') then count(status) else 0 end) as FRA_approved_current
When they should actually be returning their own numbers, and do so when ran alone, is there a case statement behaviour i'm missing here?

In standard SQL, this should not return any results (other than an error):
sum(case when facilityname like '%AT%' then count(status) else 0 end) as AT_all_status
because aggregation functions cannot be nested. Oracle does allow nesting them, but I don't commend using that functionality -- a subquery is simple enough.
In any case, I'm pretty sure that you actually intend:
sum(case when facilityname like '%AT%' then 1 else 0 end) as AT_all_status

Another way to translate your query using only one aggregate function and don't nest it is the following:
count(case when facilityname like '%AT%' then status end)

Related

PostgressSql - Table formation

I have a table in below structure which is created using postgresql
Category can have value of (Truck,Bus,Car and Bike)
Lane can have value of (Lane 1 and Lane 2)
From this table structure i need to display as below in the dashboard
I am new to DB side can anyone help in fixing this?
Thanks and Regards
SELECT cameralocation,lane, videoTime,
sum(case when (category='bike') then vehicleavgspeed else 0 end) as "Bike-Speed",
sum(case when (category='bike') then vehiclecount else 0 end) as "Bike-Count",
sum(case when (category='commercial') then vehicleavgspeed else 0 end) as "commercial-Speed",
sum(case when (category='commercial') then vehiclecount else 0 end) as "commercial-Count",
sum(case when (category='car') then vehicleavgspeed else 0 end) as "car-Speed",
sum(case when (category='car') then vehiclecount else 0 end) as "car-Count"
FROM public.inferencedata where lane='${lane}' and inferenceid='${videoTime}' group by cameralocation,lane,videoTime;

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;

Cleaning "SUM" Query

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.

SQL server Calculate with COUNT [duplicate]

This question already has an answer here:
How to use an Alias in a Calculation for Another Field
(1 answer)
Closed 4 years ago.
select
category, count(category) as 'TotalCounts',
COUNT(case kind when 'avail'then 1 else null end) as 'avail',
Count(case kind when 'offers' then 1 else null end) as 'offers',
COUNT(CASE contactMethod WHEN 'SMS' then 1 else null END) as 'SMS',
COUNT(case contactMethod when 'call' then 1 else null end) as 'call',
CONVERT(varchar(254),COUNT (case when max_biz_status='A' OR
max_biz_status ='B' then 1 else null end) * 100 / count(category)) +'%'
as 'Percetange'
from reports
group by category
order by TotalCounts
Instead of calculating again in Convert method i want to use avail* 100 / TotalCounts like i did in order by when i used TotalCounts.
i tried:
CONVERT(varchar(254),avail * 100 / TotalCounts) +'%' as 'Percetange'
but i get 'invalid column name' for avail and TotalCounts
You can't do that because your TotalCounts column is made from your result set.
you can try to use a subquery to contain it then calculation.
if your mssql version support CONCAT function you can use it let the SQL clearer.
SELECT t1.*,CONCAT((max_biz_statusCnt * 100 /TotalCounts),'%')as 'Percetange'
FROM
(
select
category,
count(*) as 'TotalCounts',
COUNT(case kind when 'avail'then 1 else null end) as 'avail',
Count(case kind when 'offers' then 1 else null end) as 'offers',
COUNT(CASE contactMethod WHEN 'SMS' then 1 else null END) as 'SMS',
COUNT(case contactMethod when 'call' then 1 else null end) as 'call',
COUNT (case when max_biz_status='A' OR max_biz_status ='B' then 1 else null end) 'max_biz_statusCnt'
from reports
group by category
) t1
order by TotalCounts
You can't use avail or TotalCounts as you just created them, so they aren't in scope, using a common-table expression is one way to fix this:
WITH cte AS (
SELECT
category,
COUNT(category) AS TotalCounts,
COUNT(case kind WHEN 'avail' THEN 1 ELSE NULL END) AS avail,
COUNT(case kind WHEN 'offers' THEN 1 ELSE NULL END) AS offers,
COUNT(CASE contactMethod WHEN 'SMS' THEN 1 ELSE NULL END) AS SMS,
COUNT(case contactMethod WHEN 'call' THEN 1 ELSE NULL END) AS [call]
FROM
reports
GROUP BY
category)
SELECT
*,
CONVERT(varchar(254),avail * 100 / TotalCounts) +'%' AS Percetange --(sic)
FROM
cte
ORDER BY
TotalCounts;

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