The below query is part of a select query which I have got in my application
where
case when o.tracking_id <> '0' then a.account_id is null
and
o.status = 'N'
else
(
o.tracking_id = '0'
and
o.status = 'N'
)
END
I am having hardtime to understand the below line
Can you please tell me what does this exactly mean ?
case when o.tracking_id <> '0' then a.account_id is null
I wouldn't use a CASE expression here but instead would use the following logic:
WHERE
(o.tracking_id <> '0' AND a.account_id IS NULL AND o.status = 'N')
OR
(o.tracking_id = '0' AND o.status = 'N')
The condition is written somewhat clumsily. It is equivalent to this more readable expression:
where (o.tracking_id = '0' or a.account is null)
and o.status = 'N';
Related
SELECT
CASE -- result#1
WHEN .. then 'a'
WHEN .. then 'b'
END,
CASE -- result#2
WHEN .. then 'c'
WHEN .. then 'd'
END,
FROM table1
I have 2 CASE expressions above, can I use the result of both CASE expressions and create another CASE expression based on the values from both CASE expressions?
CASE
WHEN result1 IS NOT NULL and result2 IS NOT NULL THEN '...'
ELSE NULL
END
You cannot use the result of a case expression at the same "block" that it is developed in. You need a sub select or a CTE.
select case
when result1 is not null
and result2 is not null
then '...'
else null
end "Final Result"
from ( select case
when .. then 'a'
when .. then 'b'
else null
end result1
, case
when .. then 'c'
when .. then 'd'
else null
end result2
from table1
) sq
OR
with first_case (result11, result22) as
( select case
when .. then 'a'
when .. then 'b'
else null
end
, case
when .. then 'c'
when .. then 'd'
else null
end
from table1
)
select case
when result1 is not null
and result2 is not null
then '...'
else null
end "Final Result"
from first_case;
I’m new to pl/SQL and would like to get some advice on whether this code snippet could be written in a more generic way.
What I mean by general is that I may get the new ‘source data’, in which the schema may vary. For example, what is currently available as:
name_1, name_2, lakename_1 in other ‘source data’ might be available under different names, and the number of the column might be also different.
Ideally would be to have one section of the code in which the names of columns could be defined. This is probably where pl/SQL come into the action.
Thank you in advance for assistance with it.
SELECT
nid,
name_1,
name_2,
lakename_1,
lakename_2,
rivname_1,
rivname_2,
concat_ws(',', "name_1", "name_2", "lakename_1", "lakename_2", "rivname_1", "rivname_2" ) concated_names,
---number of names
(
(CASE WHEN name_1 != '' THEN '1' ELSE '0' END)::integer +
(CASE WHEN name_2 != '' THEN '1' ELSE '0' END)::integer +
(CASE WHEN lakename_1 != '' THEN '1' ELSE '0' END)::integer +
(CASE WHEN lakename_2 != '' THEN '1' ELSE '0' END)::integer +
(CASE WHEN rivname_1 != '' THEN '1' ELSE '0' END)::integer +
(CASE WHEN rivname_2 != '' THEN '1' ELSE '0' END)::integer
) number_of_names,
---unique combinations of names occurence
(
(CASE WHEN name_1 != '' THEN 'name1' ELSE '' END) || ',' ||
(CASE WHEN name_2 != '' THEN 'name2' ELSE '' END) || ',' ||
(CASE WHEN lakename_1 != '' THEN 'lakename_1' ELSE '' END) || ',' ||
(CASE WHEN lakename_2 != '' THEN 'lakename_2' ELSE '' END) || ',' ||
(CASE WHEN rivname_1 != '' THEN 'rivname_1' ELSE '' END) || ',' ||
(CASE WHEN rivname_2 != '' THEN 'rivname_2' ELSE '' END)
) unique_names
,
geom
INTO canada_merged.number_of_names_per_features
FROM
canada_merged.waterbody_and_waterlines
where name_1 !=''
or name_2 !=''
or lakename_1 !=''
or lakename_2 !=''
or rivname_1 !=''
or rivname_2 !='';
For reasons too silly to explain I have three columns in a table which hold date and time values. One column only holds the date, the second only holds the time, and the third holds a DATETIME value. Looks like this:
OPPORTUNITYID | ... | ProductionDate | ProductionTime | PRODUCTIONDATETIME
-------------------------------------------------------------------------------
091798-324971 | ... | 12-07-2014 | 11:30 AM | 2014-07-12 11:30:00:000
Then I have a trigger that keeps these values in sync regardless of which is being updated.
This is (part of) the trigger:
CREATE TRIGGER [dbo].[TBL_OPPORTUNITY_DUEDATES_TRU]
ON [dbo].[TBL_OPPORTUNITY]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE ( PRODUCTIONDATETIME )
BEGIN
UPDATE TBL_OPPORTUNITY
SET ProductionDate = CONVERT(VARCHAR(10), PRODUCTIONDATETIME, 105)
, ProductionTime = REPLACE(REPLACE(RIGHT('0'+LTRIM(RIGHT(CONVERT(VARCHAR, PRODUCTIONDATETIME,100), 7)), 7), 'AM', ' AM'), 'PM', ' PM')
WHERE OPPORTUNITYID IN ( SELECT i.OPPORTUNITYID FROM inserted i
INNER JOIN deleted d ON i.OPPORTUNITYID = d.OPPORTUNITYID
WHERE NOT i.PRODUCTIONDATETIME = d.PRODUCTIONDATETIME
AND NOT ( i.PRODUCTIONDATETIME = '' OR i.PRODUCTIONDATETIME IS NULL )
);
END
IF ( UPDATE ( ProductionDate ) OR UPDATE ( ProductionTime ) )
BEGIN
UPDATE TBL_OPPORTUNITY
SET PRODUCTIONDATETIME = CONVERT(DATETIME, ProductionDate + ' ' + ProductionTime, 105)
WHERE OPPORTUNITYID IN ( SELECT i.OPPORTUNITYID FROM inserted i
INNER JOIN deleted d ON i.OPPORTUNITYID = d.OPPORTUNITYID
WHERE ( NOT i.ProductionDate = d.ProductionDate
OR NOT i.ProductionTime = d.ProductionTime )
AND NOT ( i.ProductionDate = '' OR i.ProductionDate IS NULL )
AND NOT ( i.ProductionTime = '' OR i.ProductionTime IS NULL )
);
UPDATE TBL_OPPORTUNITY
SET PRODUCTIONDATETIME = CONVERT(DATETIME, ProductionDate + ' 12:00:00', 105)
WHERE OPPORTUNITYID IN ( SELECT i.OPPORTUNITYID FROM inserted i
INNER JOIN deleted d ON i.OPPORTUNITYID = d.OPPORTUNITYID
WHERE ( NOT i.ProductionDate = d.ProductionDate
OR NOT i.ProductionTime = d.ProductionTime )
AND NOT ( i.ProductionDate = '' OR i.ProductionDate IS NULL )
AND ( i.ProductionTime = '' OR i.ProductionTime IS NULL )
);
END
END
GO
The trigger works as expected whenever any of the values are updated. However, the trigger fails (as in doesn't make any changes) if a value is being updated from NULL, or in other words, the old value in a column was NULL and the new value is, for example '02-03-2014'.
Why is that?
The server is Microsoft SQL Server 2008 R2.
Thank you for any clues.
As it is written, the trigger has to ignore rows where the old values are NULL because an equality or inequality involving NULL can never evaluate to true. A WHERE condition such as NOT i.ProductionDate = d.ProductionDate is never going to return any rows if d.ProductionDate is NULL, no matter what i.ProductionDate is. You would need to explicitly check the possibility that d.ProductionDate IS NULL to handle the cases where d.ProductionDate has no value.
Do this for every column you are tracking
DECLARE #ProductionDate Date;
DECLARE #ProductionDateOld Date;
DECLARE #ProductionDateInd bit = 0; // you can use the indicator later to determine which field changed. if = 0 it didn't change, if 1 it did change
DECLARE #ProductionDateTime DateTime;
DECLARE #ProductionDateTimeOld DateTime;
DECLARE #ProductionDateTimeInd bit = 0;
SELECT #ProductionDate=ProductionDate FROM inserted i;
SELECT #ProductionDateOld = d.ProductionDate FROM deleted d;
if #ProductionDateOld <> #ProductionDate
#ProductionDateInd = 1;
if #ProductionDateOld IS NULL AND #ProductionDate IS NOT NULL
#ProductionDateInd = 1;
SELECT #ProductionDateTime=ProductionDateTime FROM inserted i;
SELECT #ProductionDateTimeOld = d.ProductionDateTime FROM deleted d;
if #ProductionDateTimeOld <> #ProductionDateTime
#ProductionDateTimeInd = 1;
if #ProductionDateTimeOld IS NULL AND #ProductionDateTime IS NOT NULL
#ProductionDateTimeInd = 1;
Then check if a value changed (I do this to only write to history/audit table if there truly is a change)
if (#ProductionDateInd = 1 OR
#ProductionDateInd = 1)
INSERT INTO TBL_OPPORTUNITY_DUEDATES_TRU (
ProductionDate,
ProductionDateInd,
ProductionDateTime,
ProductionDateTimeInd,
.
.
.
)
VALUES (
#ProductionDate,
#ProductionDateInd,
#ProductionDateTime,
#ProductionDateTimeInd,
.
.
.
)
SELECT user
FROM userlist zH with(nolock)
where zH.user in (case when zh.trait='1' then ('B', 'HO', 'KO', 'PL','APP','2A','2B') else ('O') end)
can this statement with the where-in-case work? i hope you get what i meant. thanks.
You can use nested case statement, like
SELECT user
FROM userlist zH with(nolock)
where 'true' =
(case when zh.trait = '1'
then
case when zH.user in ('B', 'HO', 'KO', 'PL','APP','2A','2B')
then 'true'
else 'false'
end
else
case when zH.user = 'O'
then 'true'
else 'false'
end
end)
SELECT [user]
FROM userlist zH WITH ( NOLOCK )
WHERE ( zh.trait = '1'
AND zH.[user] IN ( 'B', 'HO', 'KO', 'PL', 'APP', '2A', '2B' )
)
OR ( zh.trait <> '1'
AND zH.[user] IN ( 'O' )
)
I have parameters like these
declare #Phl1_descr varchar(50)
SET #Phl1_descr = 'Greece'
declare #Phl2_descr varchar(50)
SET #Phl2_descr = 'Coffee & Beverages'
I want to join two tables with the above parameters (if they are not null), so I tried to do something like below in the "ON" keyword of my JOIN
ON
(CASE WHEN LEN(#Phl1_descr) > 0 THEN A.Phl1_descr ELSE B.Phl1_descr END) = B.Phl1_descr AND
(CASE WHEN LEN(#Phl2_descr) > 0 THEN A.Phl2_descr ELSE B.Phl2_descr END) = B.Phl2_descr
However if I send one of the parameters like as '', it doesn't work. Any simpler idea?
Is it posible to use simpler solution? Like:
IF #Phl1_descr IS NOT NULL AND #Phl2_descr IS NOT NULL
BEGIN
SELECT *
FROM Table1 as A
LEFT JOIN Table2 as B on A.Phl1_descr=B.Phl1_descr and A.Phl2_descr=B.Phl2_descr
END
ELSE IF #Phl1_descr IS NOT NULL AND #Phl2_descr IS NULL
BEGIN
SELECT *
FROM Table1 as A
LEFT JOIN Table2 as B on A.Phl1_descr=B.Phl1_descr
END
ELSE IF #Phl1_descr IS NULL AND #Phl2_descr IS NOT NULL
BEGIN
SELECT *
FROM Table1 as A
LEFT JOIN Table2 as B on A.Phl2_descr=B.Phl2_descr
END
So you will get a simpler execution plans and simpler logic.
You can also use ... CASE WHEN #Phl1_descr IS NULL THEN ... to check NULL values
Interesting but
B.Phl1_descr = B.Phl1_descr
not working but
ISNULL(B.Phl1_descr,'-1') = ISNULL(B.Phl1_descr,'-1')
works,
So just a simple change in the below code work it out
(CASE WHEN LEN(#Phl1_descr) > 1 THEN A.Phl1_descr ELSE ISNULL(B.Phl1_descr,'-1') END) = ISNULL(B.Phl1_descr,'-1') AND
(CASE WHEN LEN(#Phl2_descr) > 1 THEN A.Phl2_descr ELSE ISNULL(B.Phl2_descr,'-1') END) = ISNULL(B.Phl2_descr,'-1') AND