Optimize multiple case expressions with THEN/END - postgresql

I have following query.
SELECT
i.id,
CASE WHEN ia.detail_count = 1 THEN i.space_id ELSE NULL END AS space_id,
CASE WHEN ia.detail_count = 1 THEN i.resident_id ELSE NULL END AS resident_id,
CASE WHEN ia.detail_count = 1 THEN i.lease_id ELSE NULL END AS lease_id,
i.deleted_by,
i.deleted_on,
i.updated_by,
i.updated_on,
i.created_by
From
myTable i
JOIN (
SELECT
icd.id,
json_build_object(
'lease_ids', array_remove(array_agg(icd.lease_id), NULL),
'resident_ids', array_remove(array_agg(icd.resident_id), NULL),
'space_ids', array_remove(array_agg(icd.space_id), NULL)
) AS details,
COUNT(icd.id) As detail_count
FROM
mytable_details icd
GROUP BY
icd.id
) ia ON ia.id = i.id;
Can we optimize following three expressions into 1, since condition is same only operand is different.
CASE WHEN ia.detail_count = 1 THEN i.space_id ELSE NULL END AS space_id,
CASE WHEN ia.detail_count = 1 THEN i.resident_id ELSE NULL END AS resident_id,
CASE WHEN ia.detail_count = 1 THEN i.lease_id ELSE NULL END AS lease_id,

I'm not sure that this counts as an optimisation, but I think you could modify the inner query:
(COUNT(icd.id) = 1) as one_detail
... which would return a Boolean result, and then ...
case when one_detail then i.space_id end as space_id,
case when one_detail then i.resident_id end as resident_id,
case when one_detail then i.lease_id end as lease_id,
I'm not sure it's worthwhile in a simple case like this, but for a more complex condition it might be.

Related

Case When isnt returning data for the null

I have a case statement that is not returning a null value. What am I missing in to get this to work.
Select CASE
WHEN transfer_sources.input_lot_type = 'Dried' THEN Sum(transfer_sources.weight)
WHEN transfer_sources.input_lot_type = 'Fresh' THEN NULL
END
from transfer_sources join bulk_lots on transfer_sources.source_id = bulk_lots.id
where transfer_sources.input_lot_type = 'Dried' and bulk_lots.name = 'BS190208-010'
group by transfer_sources.input_lot_type
LIMIT 1
I would like a null to show in the fresh column as i am trying to only calculate for dried
You need to remove WHERE condition transfer_sources.input_lot_type = 'Dried':
Select CASE
WHEN transfer_sources.input_lot_type = 'Dried' THEN Sum(transfer_sources.weight)
WHEN transfer_sources.input_lot_type = 'Fresh' THEN NULL
END
from transfer_sources join bulk_lots on transfer_sources.source_id = bulk_lots.id
where bulk_lots.name = 'BS190208-010'
group by transfer_sources.input_lot_type

Case statement to ISNULL

I am very new to T-SQL and am looking to simplify this query using isnull.
case
when datediff(d, appdate, disdate) IS NOT NULL THEN datediff(d, appdate, disdate)
ELSE
Case
when appdate is null THEN datediff(d,update,getdate())
when disdate IS NULL THEN datediff(d,appdate,getdate())
END
END
Not much of a simplification but this should do the same thing:
ISNULL(datediff(d, appdate, disdate) ,
CASE WHEN appdate IS NULL THEN datediff(d,update,getdate())
WHEN disdate IS NULL THEN datediff(d,appdate,getdate()) END
)

Determine Group By from Parameter -

How is it that this is valid:
ALTER PROCEDURE [StoredProcedure]
#abcID int = null -- optional param
SELECT columnJ, columnK, Count(eID) AS Num, Sum(OutXYZ) as TotalProdXYZ, Sum(RawXYZ) as TotalRawXYZ
FROM [v_ViewTable]
WHERE (#abcID IS NULL OR (abcID = #abcID))
GROUP BY columnJ, columnK
But then this is throwing a "columnJ is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause."
ALTER PROCEDURE [StoredProcedure]
#abcID int = null -- optional param
-- if 0: Group by columnJ, columnK
-- else: Group by columnK, columnJ
, #Grouping int = null
SELECT columnJ, columnK, Count(eID) AS Num, Sum(OutXYZ) as TotalProdXYZ, Sum(RawXYZ) as TotalRawXYZ
FROM [v_ViewTable]
WHERE (#abcID IS NULL OR (abcID = #abcID))
GROUP BY
CASE WHEN #Grouping = 0 THEN columnJ ELSE columnK END
,CASE WHEN #Grouping = 0 THEN columnK ELSE columnJ END
What's wrong with my CASE statement? Basically, if #Grouping = 0, I want the group by to be J, K if anything else, it should be K, J
Thanks in advance for any help!
As the message says columnJ and columnK are not contained in either an aggregate function or the GROUP BY clause in the second case. You should use field or the exact expression in select list AS IS in the GROUP BY section.
So the following statement will be ok:
SELECT CASE WHEN #Grouping = 0 THEN columnJ ELSE columnK END,
CASE WHEN #Grouping = 0 THEN columnK ELSE columnJ END,
Count(eID) AS Num, Sum(OutXYZ) as TotalProdXYZ, Sum(RawXYZ) as TotalRawXYZ
FROM [v_ViewTable]
WHERE (#abcID IS NULL OR (abcID = #abcID))
GROUP BY
CASE WHEN #Grouping = 0 THEN columnJ ELSE columnK END
,CASE WHEN #Grouping = 0 THEN columnK ELSE columnJ END

CREATE VIEW if 'a' not null and 'b' not null then return 'a' and 'b' else null

I am creating a view in postgres using the pgAdmin SQL window and having real trouble with the syntax for a particular part of the query.
I'd like to be able to state: where both a and b are not null then return the values for a and b, else return null.
I've started off looking at the CASE THEN ELSE statement but really can't figure this out. Any help greatly appreciated.
SELECT a, b,
CASE
WHEN a IS NOT NULL AND b IS NOT NULL
THEN a = a AND b = b
ELSE false
END
SELECT a,b,
case when a is not null and b is not null then a else null end,
case when a is not null and b is not null then b else null end

How do I use T-SQL's Case/When?

I have a huge query which uses case/when often. Now I have this SQL here, which does not work.
(select case when xyz.something = 1
then
'SOMETEXT'
else
(select case when xyz.somethingelse = 1)
then
'SOMEOTHERTEXT'
end)
(select case when xyz.somethingelseagain = 2)
then
'SOMEOTHERTEXTGOESHERE'
end)
end) [ColumnName],
Whats causing trouble is xyz.somethingelseagain = 2, it says it could not bind that expression. xyz is some alias for a table which is joined further down in the query. Whats wrong here? Removing one of the 2 case/whens corrects that, but I need both of them, probably even more cases.
SELECT
CASE
WHEN xyz.something = 1 THEN 'SOMETEXT'
WHEN xyz.somethingelse = 1 THEN 'SOMEOTHERTEXT'
WHEN xyz.somethingelseagain = 2 THEN 'SOMEOTHERTEXTGOESHERE'
ELSE 'SOMETHING UNKNOWN'
END AS ColumnName;
As soon as a WHEN statement is true the break is implicit.
You will have to concider which WHEN Expression is the most likely to happen. If you put that WHEN at the end of a long list of WHEN statements, your sql is likely to be slower. So put it up front as the first.
More information here: break in case statement in T-SQL
declare #n int = 7,
#m int = 3;
select
case
when #n = 1 then
'SOMETEXT'
else
case
when #m = 1 then
'SOMEOTHERTEXT'
when #m = 2 then
'SOMEOTHERTEXTGOESHERE'
end
end as col1
-- n=1 => returns SOMETEXT regardless of #m
-- n=2 and m=1 => returns SOMEOTHERTEXT
-- n=2 and m=2 => returns SOMEOTHERTEXTGOESHERE
-- n=2 and m>2 => returns null (no else defined for inner case)
If logical test is against a single column then you could use something like
USE AdventureWorks2012;
GO
SELECT ProductNumber, Category =
CASE ProductLine
WHEN 'R' THEN 'Road'
WHEN 'M' THEN 'Mountain'
WHEN 'T' THEN 'Touring'
WHEN 'S' THEN 'Other sale items'
ELSE 'Not for sale'
END,
Name
FROM Production.Product
ORDER BY ProductNumber;
GO
More information - https://learn.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql?view=sql-server-2017