Display 0 where condition doesnt match - sql

I need to write a query where I need to display 0 where source system havent sent any data for today, if I write simple query with count(*) it provides me no rows. I am using case statement but not successful to display actual count.
select SRC_SYS,
case
when ( select count (*) from table1 where SRC_SYS ='A')='0' then '0'
else count(1) end as Count
This is working fine when there is no data, but when I have data its not displaying the actual count

when I have data its not displaying actual count
Er.. No, indeed it won't; it will display "1" because there is only one row; the dataset you're count(1)ing has only one row
Just do the count from the actual table; it'll work fine whether there are 0 rows or more because the select list only contains constants or aggregates:
select 'A' as SRC_SYS, COUNT(*)
from table1
where SRC_SYS ='A'
Or if your front end is using parameters:
select #pwhatever as SRC_SYS, COUNT(*)
from table1
where SRC_SYS = #pwhatever
See this fiddle and change the where 1=0 to where 1=1 to see the count change

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.

How to get 0 if no row found from sql query in sql server

I am getting blank value with this query from sql server
SELECT TOP 1 Amount from PaymentDetails WHERE Id = '5678'
it has no row,that is why its returning blank,So I want if no row then it should return 0
I already tried with COALESCE ,but its not working
how to solve this?
You are selecting an arbitrary amount, so one method is aggregation:
SELECT COALESCE(MAX(Amount), 0)
FROM PaymentDetails
WHERE Id = '5678';
Note that if id is a number, then don't use single quotes for the comparison.
To be honest, I would expect SUM() to be more useful than an arbitrary value:
SELECT COALESCE(SUM(Amount), 0)
FROM PaymentDetails
WHERE Id = '5678';
You can wrap the subquery in an ISNULL:
SELECT ISNULL((SELECT TOP 1 Amount from PaymentDetails WHERE Id = '5678' ORDER BY ????),0) AS Amount;
Don't forget to add a column (or columns) to your ORDER BY as otherwise you will get inconsistent results when more than one row has the same value for Id. If Id is unique, however, then remove both the TOP and ORDER BY as they aren't needed.
You should never, however, use TOP without an ORDER BY unless you are "happy" with inconsistent results.

SQL Multiple Conditions in max statement not working

I am attempting to filter my table and get the item that sold for the most amount of money. In order to do this I am using "AuctionOpen" to determine whether or not the auction is still open. The auction cannot be open and have the item been sold (later I will use this for the most expensive item available).
I am able to use the AND operator to compare AuctionOpen by using the following:
select s.*
from auctionsite.dbo.Auction s
where s.HighestBid = (select max(s2.HighestBid) from auctionsite.dbo.Auction
s2) and s.AuctionOpen = 0;
When I set this equal to zero I get results, but when I set it equal to 1, it only returns the column titles even though there are values set to 1 in the table.
Results when compared to 0:
Results when compared to 1:
Clearly, the highest bid is on a record where AuctionOpen <> 1.
I recommend using order by and fetch (or the equivalent in your database):
select s.*
from auctionsite.dbo.Auction s
where s.AuctionOpen = 0
order by s.HIghestBid desc
fetch first 1 row only
In SQL Server, use either select top (1) or offset 0 rows fetch first 1 row only.
I think you should try the Count aggregate function
here, try this:
**Select count(Item_name) As
[Item with the highest money]
from table_name
Group by Item_name DSEC;**
You can check my page hereSQL/MySQL tips for some SQL/MySQL lessons

Specifying a column value in an aggregate function vs using a WHERE clause

I have a database people that looks like this:
I wanted to count the occurrences of state='CA'.
My first attempt was:
SELECT COUNT(state='CA')
FROM people
;
this returned 1 row with a value of 1000. So I thought that there were 1000 people from CA in the database.
This turns out to be incorrect. I know that they are 127, which I can verify with the query
SELECT COUNT(*)
FROM people
WHERE state='CA'
;
which returns 1 row with a value of 127.
I understand how the second query works. However, I do not understand what is wrong with the first one. What is it returning?
If you want to see what's going on, run the query:
select state='CA' from people;
You will see that you will get one result for each row in people, with the value 0 or 1 (or True/False). What you've selected is whether state='CA' for each row, and there will be just as many of those results as there are rows.
You can't constrain a COUNT statement within the statement, you have to do that via the WHERE clause as in your second example.
count is not a sum .. your first query is improper because don't return the number of the rows true .. but the total numbers of not null rows true or false
if you want a filter count you must use a where condition (as your second query) otherwise you must use an if or a a select case inside the sum() function eg:
Select sum(case
when state='CA' then 1 else 0
end) as my_result from People;
or if you want count .. use null and not 0min count
Select count(case
when state='CA' then 1 else null
end) as my_result from People;
Try this-:
Select count(case when state='CA' then 1 else null end) as xyz from People;
1st query will work if you use case when in side count,
like below query will returned count of CA
SELECT sum( case when state='CA' then 1 else 0 end)
FROM people
In first query it is assigning the value 'CA' to the column state for all 1000 rows instead of filtering the values. That is what SELECT does. SELECT does not filter the number of returning rows, it modifies the data.
Whereas in WHERE clause the rows are being filtered first then the SELECT clause runs the COUNT function.
There is a sequence for running the query. It starts from FROM then WHERE, GROUP BY, ORDER BY at the end SELECT will run.
To answer the actual question - why do you get 1000? I'm guessing that there are 1000 rows in your database, or at least 1000 where state is not null. Count will return the number of rows where the thing inside the () is not null and as one of your comments says, the part inside your () will return either true or false, neither of which is null, so will count them all. Your second example is of course the right way to do it.

PostgreSQL - Handling empty query result

I am quite new to SQL and I am currently working on some survey results with PostgreSQL. I need to calculate percentages of each option from 5-point scale for all survey questions. I have a table with respondentid, questionid, question response value. Demographic info needed for filtering datacut is retrieved from another table. Then query is passed to result table. All queries texts for specific datacuts are generated by VBA script.
It works OK in general, however there's one problematic case - when there are no respondents for specific cut and I receive empty table as query result. If respondent count is greater than 0 but lower than calculation threshold (5 respondents) I am getting table full of NULLs which is OK. For 0 respondents I get 0 rows as result and nothing is passed to result table and it causes some displacement in final table. I am able to track such cuts as I am also calculating respondent number for overall datacut and storing it in another table. But is there anything I can do at this point - generate somehow table full of NULLs which could be inserted into result table when needed?
Thanks in advance and sorry for clumsiness in code.
WITH ItemScores AS (
SELECT
rsp.questionid,
CASE WHEN SUM(CASE WHEN rsp.respvalue >= 0 THEN 1 ELSE 0 END) < 5 THEN
NULL
ELSE
ROUND(SUM(CASE WHEN rsp.respvalue = 5 THEN 1 ELSE 0 END)/CAST(SUM(CASE
WHEN rsp.respvalue >= 0 THEN 1 ELSE 0 END) AS DECIMAL),2)
END AS 5spercentage,
... and so on for frequencies of 1s,2s,3s and 4s
SUM(CASE WHEN rsp.respvalue >= 0 THEN 1 ELSE 0 END) AS QuestionTotalAnswers
FROM (
some filtering applied here [...]
) AS rsp
GROUP BY rsp.questionid
ORDER BY rsp.questionid;
INSERT INTO results_items SELECT * from ItemScores;
If you want to ensure that the questionid column won't be empty, then you must call a cte with its plain values and then left join with the table that actually you are using to make the aggregations, calcs etc. So it will generate for sure the first list and then join its values.
The example of its concept would be something like:
with calcs as (
select questionid, sum(respvalue) as sum_per_question
from rsp
group by questionid)
select distinct rsp.questionid, calcs.sum_per_question
from rsp
left join calcs on rsp.questionid = calcs.questionid