Dynamically set the result of a TSQL query using CASE WHEN - sql

SELECT MyTable.Name,
(
SELECT CASE WHEN ISNULL(SUM(TotalDays), 0) <= 0 THEN 0
ELSE SUM(TotalDays)
END AS Total
FROM Application AS Applications
WHERE (ID = MyTable.id)
) - MIN(Assignments) AS Excesses
FROM MyTable
The above TSQL statement is a subquery in a main query. When i run it, if TotalDays is NULL or <=0, then Total is set to 0 (zero).
What i would like to do here is to set the result of the whole query(Excesses) to 0. I want (Excesses) which is the result of Total - Min(Assignments) to be set to 0 if its NULL or <=0.
I want the CASE WHEN to apply to the whole query but am struggling to get it right.

SELECT
MyTable.Name,
CASE WHEN
0 < (SELECT SUM(TotalDays) FROM Application WHERE ID = MyTable.id) - MIN(Assignments)
THEN
(SELECT SUM(TotalDays) FROM Application WHERE ID = MyTable.id) - MIN(Assignments)
ELSE
0
END AS [Excesses]
FROM
MyTable
Note: MS SQL Server won't exexute the two correlated-sub-queries independantly, it will infact recognise that they are the same and re-use the results.
Alternative:
SELECT
MyTable.Name,
CASE WHEN
0 < SUM([application].TotalDays) - MIN([MyTable].Assignments)
THEN
SUM([application].TotalDays) - MIN([MyTable].Assignments)
ELSE
0 -- If either aggregate is NULL, 0 will still be returned
END AS [Excesses]
FROM
MyTable
LEFT JOIN
Application
ON [application].ID = [MyTable].id

SELECT MyTable.Name, CASE WHEN ISNULL(SUM(TotalDays), 0) <= 0 THEN 0 ELSE SUM(TotalDays) END AS Total
FROM Application AS Applications
JOIN MyTable
ON Applications.id = mytable.id
GROUP BY
MyTable.id, MyTable.name
HAVING CASE WHEN ISNULL(SUM(TotalDays), 0) <= 0 THEN 0 ELSE SUM(TotalDays) END > 0

Related

Postgres: missing FROM-clause entry for table - SQL

good afternoon I have a query that I am not able to show the column of the table (dpa.view_workflowjob_client) column (f_name), when I place (c.f_name) do not select to view the error (missing entry from the FROM clause for the table). see below:
select
wfjc.f_agent_name,
wfjc.f_policy_name,
wfjc.f_workflow_name,
wfjc.f_workflow_jobid,
wfjc.f_status,
wfjc.f_completion_status,
wfjc.f_completion_report,
wfjc.f_starttime,
wfjc.f_endtime,
wfjc.f_missed_clients,
wfjc.f_disabled_clients,
c.f_name
from (
select *
from dpa.view_workflowjob wfj
left join
(
select
c.f_workflowjob_id,
case when count(c.dis) > 0
then count(c.dis)
else null
end f_disabled_clients,
case when count(c.msd) > 0
then count(c.msd)
else null
end f_missed_clients
from
(
select
f_name,
f_workflowjob_id,
case when f_status = 'disabled'
then 1
else null
end dis,
case when f_status = 'missed'
then 1
else null
end msd
from dpa.view_workflowjob_client
where f_starttime <= 1606146420 AND f_endtime >= 1605023220
) c
group by c.f_workflowjob_id
) clients
on clients.f_workflowjob_id = wfj.f_id
) wfjc
where (
(wfjc.f_starttime <= 1606146420 AND wfjc.f_endtime >= 1605023220 AND ( (wfjc.f_agent_id = '8512813a-5654-4b18-99cc-0e812076e719') ))
)

How to use an SQL Comparator in the base 'Case' selector in the 'When' logic without having to re-write conditions

I have an SQL query joined on multiple tables (all INNER JOINS).
The below is an example of the query I am trying to run (the ? is to illustrate the position in which I presume the answer to my question will be rectified).
Case
(
SELECT Count(ID)
FROM CPD_Candidates cpdCan
WHERE
cpdCan.CandidateID = can.CandidateID
AND
(
cpdCan.DateEnded >= GETDATE()
OR
coalesce(cpdCan.DateEnded, '') = N'1-Jan-1900'
)
AND
cpdCan.Deleted <> 1
)
When ? > 0 then 'Bigger' else 'Equal or Smaller' End
)
The idea with the above is that instead of the ? the actual value I want to compare against would be Count(ID), if it's greater than 0 I want it to SELECT 'Bigger', otherwise it should SELECT 'Equal or Smaller'. So a more-accurate depiction of what I wish to run would be the below.
Case
(
SELECT Count(ID)
FROM CPD_Candidates cpdCan
WHERE
cpdCan.CandidateID = can.CandidateID
AND
(
cpdCan.DateEnded >= GETDATE()
OR
coalesce(cpdCan.DateEnded, '') = N'1-Jan-1900'
)
AND
cpdCan.Deleted <> 1
)
When
Count(cpdCan.ID) > 0 then 'Bigger' else 'Equal or Smaller' End
)
Of course there is a syntax error above but I am enquiring as to whether it is possible to compare like in the above SQL query structure but replacing Count(cpdCan.ID) > 0 with some other means to achieve that value & logic?
If this is un-achievable in SQL Server 2016 what other means would be a better solution to this XY?
I think that you mean:
case when
(
SELECT Count(ID)
FROM CPD_Candidates cpdCan
WHERE
cpdCan.CandidateID = can.CandidateID
AND (cpdCan.DateEnded >= GETDATE() OR coalesce(cpdCan.DateEnded, '') = N'1-Jan-1900')
AND cpdCan.Deleted <> 1
) > 0
then 'Bigger'
else 'Equal or Smaller'
End

returning the column values as a list or else 0

I had a query where i am trying to get the results of a query, the query can have multiple rows or it can be empty, i am trying if it is empty, it should return me 0 for a column i am looking which is called as sequence
My query is like this:
select CASE WHEN COUNT(1) > 0 THEN 1 ELSE 0 END AS Sequence
from dbo.mytable
it returns me the either 1 or 0, for 1 i want that column should return me values or it should combine all the rows and return me the value of that column as list like 1,2,3,4,5,6,7
This should work.
SELECT
CASE WHEN MY_COUNT > 0 THEN 1 ELSE 0 END AS SEQUENCE
FROM
(SELECT COUNT(*) AS MY_COUNT
FROM
DBO.MYTABLE);
If you want only one row in the result set, simply do:
select (case when count(*) > 0 then 1 else 0 end) as sequence
from mytable;
If you care at all about performance, the more efficient method is:
select (case when exists (select 1 from dbo.mytable) then 1 else 0
end) as sequence

SQL MAX value of two sub queries

I have two queries and I want to get the maximum value of the two of them.
MAX((SELECT COUNT(p.[ItemID]) FROM [dbo].[Table] p WHERE HasHuman=0),
(SELECT COUNT(p.[ItemID]) FROM [dbo].[Table] p WHERE HasHuman=1))
You can calculate both result in a single query and then apply TOP:
select top 1
HasHuman,
COUNT(p.[ItemID]) as cnt
from [dbo].[Table]
group by HasHuman
order by cnt desc
You could even do this in a single query:
SELECT
CASE WHEN SUM(CASE WHEN HasHuman=0 THEN 1 ELSE 0 END) >
SUM(CASE WHEN HasHuman=1 THEN 1 ELSE 0 END)
THEN SUM(CASE WHEN HasHuman=0 THEN 1 ELSE 0 END)
ELSE SUM(CASE WHEN HasHuman=1 THEN 1 ELSE 0 END) END
FROM [dbo].[Table]
WHERE ItemID IS NOT NULL -- you were not counting NULLs
SELECT MAX(RC)
FROM (SELECT COUNT(p.ItemID) AS RC FROM dbo.[Table]
WHERE HasHuman=0
UNION
SELECT COUNT(p.ItemID) AS RC FROM dbo.[Table]
WHERE HasHuman=1
) A

How to execute multiple case when statements for each iteration in SAS?

I'm using proc sql, and using multiple case when statements to add columns with either a 0 or 1 if the condition is met. It's a big bottleneck right now since it has to scan through each id for each case when statement. So I'm trying to figure out a way to somehow nest the case statements to perform each iteration, instead of having to iterate for all case statements.
This is an example of my code that is taking too long right now.
SELECT *,
CASE WHEN loannumber IN (
SELECT loannumber FROM PREPAY_LOAN_IDS
) THEN 1
ELSE 0 END AS PREPAY_FLAG,
CASE WHEN loannumber IN (
SELECT loannumber FROM DPD_30_IDS
) THEN 1
ELSE 0 END AS DPD_30_FLAG,
CASE WHEN loannumber IN (
SELECT loannumber FROM DPD_60_IDS
) THEN 1
ELSE 0 END AS DPD_60_FLAG,
CASE WHEN loannumber IN (
SELECT loannumber FROM DPD_90_IDS
) THEN 1
ELSE 0 END AS DPD_90_FLAG,
CASE WHEN loannumber IN (
SELECT loannumber FROM DPD_120_IDS
) THEN 1
ELSE 0 END AS DPD_120_FLAG,
CASE WHEN loannumber IN (
SELECT loannumber FROM FORECLOSURE_IDS
) THEN 1
ELSE 0 END AS FORECLOSURE_FLAG
FROM(
SELECT *
FROM MORTGAGES
)
The below query will work faster than the one you have posted as the input table is not completely access to retrieve the results. Try running this query and see how it performs.
SELECT M.*,
CASE WHEN PLI.loannumber IS NOT NULL THEN 1
ELSE 0 END AS PREPAY_FLAG,
CASE WHEN D3I.loannumber IS NOT NULL THEN 1
ELSE 0 END AS DPD_30_FLAG,
CASE WHEN D6I.loannumber IS NOT NULL THEN 1
ELSE 0 END AS DPD_60_FLAG,
CASE WHEN D9I.loannumber IS NOT NULL THEN 1
ELSE 0 END AS DPD_90_FLAG,
CASE WHEN D12I.loannumber IS NOT NULL THEN 1
ELSE 0 END AS DPD_120_FLAG,
CASE WHEN FCI.loannumber IS NOT NULL THEN 1
ELSE 0 END AS FORECLOSURE_FLAG
FROM MORTGAGES M
LEFT JOIN
PREPAY_LOAN_IDS PLI
ON M.loannumber = PLI.loannumber
LEFT JOIN
DPD_30_IDS D3I
ON M.loannumber = D3I.loannumber
LEFT JOIN
DPD_30_IDS D6I
ON M.loannumber = D6I.loannumber
LEFT JOIN
DPD_90_IDS D9I
ON M.loannumber = D9I.loannumber
LEFT JOIN
DPD_90_IDS D12I
ON M.loannumber = D12I.loannumber
LEFT JOIN
FORECLOSURE_IDS FCI
ON M.loannumber = FCI.loannumber
;
Since you're using SAS, here's a data step alternative, assuming that each of your datasets is already either sorted by or has an index on loannumber:
data want;
merge MORTGAGES(in = Mortgages)
PREPAY_LOAN_IDS(in = PLIDs keep = loannumber)
/*etc*/
;
by loannumber;
if Mortgages;
PREPAY_FLAG = PLIDs;
/*etc*/
run;
N.B. You will get duplicated records from MORTGAGES if you have duplicates in any of your other tables.