I have been working on figuring out how to accomplish the following for a few days now:
I have one table which has alternate addresses, but I only need to pull the city. However the city might be in field5,field4, or field3. What I would like to do, and have failed miserably, is to populate another field called city with the value found through evaluating the three fields for <> NULL.
This is what I have so far, although I'm not receiving any errors, the only value that appears is field4, since field5 is null or ''. But if field4 is also null, the city field is blank. For some reason my query is not looking at field3 and if there is a value, the value won't populate. Help please!
This is the 1st attempt:
case when altcity='Y' and (field5 IS null OR field5=' ' )
then field4 else
case when altcity='Y' and (field4 IS null OR field4=' ')
then field3
else field5
end
end as city <- Field5 or Field4 appears as it should, but if both fields are null, the field is blank. Looks as if the query doesn't look at field3.
Here is the second attempt:
case when altcity='y' then coalesce(field5,field4,field3) end as city
Same thing here, the value in field5 or field4 is populated, but the value for field3 does not.
Thank you already very much for assisting!
A bit long handed but what does the following look like when run against your data:
CASE
WHEN altcity='y' THEN
CASE
WHEN field5 is not null AND field5 != '' THEN field5
WHEN ((field5 is null) OR (field5 = '')) and ((field4 is not null) AND (field4 != '')) then field4
WHEN (((field5 is null) OR (field5 = '')) and ((field4 is null) OR (field4 = ''))) and ((field3 is not null) AND (field3 != '')) then field3
ELSE '?'
END
END
Having seen an example of your data it now makes sense that the COALESCE didn't work as that is reliant on NULL's in the data. In C# there is a string function IsNullOrEmpty that handles these cases. T-SQL doesn't have this but there are examples like this that help create that functionality and could tidy up the case statement
Related
One of the column ( called details ) in my table is of jsonb data type and have data format somthing like this:
{"media_height":"350", "media_height":"450", "media_alt":"", "file_name":"myfile.jpeg"}
This field I am taking in case when because I want to mark the records of missing alt text.
SELECT
distinct ON ( p.property_name )
p.id, p.property_name,
CASE
WHEN mma.id IS NULL THEN 'Z'
WHEN mma.details->'media_alt'::TEXT IS NULL THEN 'NO'
ELSE 'YES' END as has_media_alt
FROM properties p
LEFT JOIN marketing_media_associations mma ON ( mma.reference_id = p.id )
GROUP BY p.id, p.property_name , mma.details->'media_alt', mma.id
ORDER BY p.property_name, has_media_alt ASC
The above query gives me accurate results for Z, but it never goes in NO block. What I am missing here?
An empty string is not the same as NULL, you probably want:
WHEN nullif(mma.details->>'media_alt', '') IS NULL THEN 'NO'
You don't need to cast to text, if you use ->> which returns the value as text directly.
I need to further refine my stored proc resultset from this post, I need to filter my resultset to display only records where emailaddr is NULL (meaning display only records that have Invoice_DeliveryType value of 'N' ).
Among numerous queries, I have tried:
select
Invoice_ID, 'Unknown' as Invoice_Status,
case when Invoice_Printed is null then '' else 'Y' end as Invoice_Printed,
case when Invoice_DeliveryDate is null then '' else 'Y' end as Invoice_Delivered,
(case when Invoice_DeliveryType <> 'USPS' then ''
when exists (Select 1
from dbo.Client c
Where c.Client_ID = SUBSTRING(i.Invoice_ID, 1, 6) and
c.emailaddr is not null
)
then 'Y'
else 'N'
end)
Invoice_ContactLName + ', ' + Invoice_ContactFName as ContactName,
from
dbo.Invoice
left outer join
dbo.fnInvoiceCurrentStatus() on Invoice_ID = CUST_InvoiceID
where
CUST_StatusID = 7
AND Invoice_ID = dbo.Client.Client_ID
AND dbo.client.emailaddr is NULL
order by
Inv_Created
but I get an error
The conversion of the nvarchar value '20111028995999' overflowed an int column
How can I get the stored procedure to only return records with DeliveryType = 'N' ?
Trying selecting the stored proc results into a temp table, then select
* from #TempTable
We could really do with a schema definition to get this problem resolved.
It appears that there is an implicit conversion occurring within one of your case statements, but without the schema def's it's difficult to track down which one.
You can't safely mix datatypes in CASE expressions, unless you are absolutely sure that any implicit conversions will work out OK you should make the conversions explicit.
Judging by the error message seeming to include something that could be a date represented as a string(20111028) plus some kind of other data ?time?(995999) it may be something to do with Invoice_DeliveryDate, but this is a shot in the dark without more details.
Which statement is perfect or better when dealing with billion of records for comparing NULL's in merge statement. I have tried with SET ANSI_NULLS OFF but that didn't work in merge statement. Here is my two ways
ISNULL(SRCColumn,-11111) = ISNULL(DSTColumn, -11111)
Or
SRCColumn = DSTColumn OR (SRCColumn IS NULL AND DSTColumn IS NULL)
Please let me know if there is any better way to deal with it. As I have around 15 columns to compare.
SRCColumn = DSTColumn OR (SRCColumn IS NULL AND DSTColumn IS NULL)
I'd suggest that you use this version because it most accurately expresses what you want SQL Server to do.
Both statements are logically equivalent (unless -11111 is a legal value for the column), however this statement is much more recognizable, and there's probably only a negligible difference in the run-time performance of the two statements.
If you are more concerned with succinctness than performance, CHECKSUM() is also an option. It will match NULL -> NULL:
MERGE A
USING B
ON A.Key = B.Key
WHEN MATCHED AND CHECKSUM(A.Col1, A.Col2, ... ) <> CHECKSUM(B.Col1, B.Col2, ... )
THEN UPDATE SET Col1 = B.Col1, Col1 = B.Col2, ...
How about using the NOT comparison on matching:
MERGE [TGT]
USING [SRC]
ON [SRC].Key = [TGT]. Key
…
WHEN MATCHED AND
(
NOT ([TGT].[dw_patient_key] = [SRC].[dw_patient_key] OR ([TGT].[dw_patient_key] IS NULL AND [SRC].[dw_patient_key] IS NULL))
OR NOT ([TGT].[dw_patient_key] = [SRC].[dw_patient_key] OR ([TGT].[dw_patient_key] IS NULL AND [SRC].[dw_patient_key] IS NULL))
...
)
THEN UPDATE
...
I have written a recursive function and depending on the output I need to select different fields. My question is now, how can I do this multiple times without having to call the function more then once? What I'm doing right now is just using the CASE WHEN... condition and checking every time what the functions return. (This is only a pseudo code and doesn't do anything real, it's just for understanding)
SELECT
id,
(CASE WHEN (function(id) > 0)
THEN field1
ELSE field2
END) as value1,
(CASE WHEN (function(id) > 0)
THEN field3
ELSE field4
END) as value2,
(CASE WHEN (function(id) > 0)
THEN field5
ELSE field6
END) as value3
FROM table1
...
How can I optimize this query and call the function only once?
Thanks in advance!
If the function is declared IMMUTABLE, it is safe to call it many times, as it will not be reevaluated.
From the docs:
IMMUTABLE indicates that the function cannot modify the database and always returns the same result when given the same argument values; that is, it does not do database lookups or otherwise use information not directly present in its argument list. If this option is given, any call of the function with all-constant arguments can be immediately replaced with the function value.
use a subquery :
SELECT foo, bar, result
FROM (
SELECT ..., function(id) AS result
....
) as tmp
You may be able to use some funky tuple thing like:
SELECT id,
CASE WHEN function(id) > 0
THEN (field1, field3, field5)
ELSE (field2, field4, field6)
END as (value1, value2, value3)
but I have no experience with this syntax
I want to write a simple calculation to return a value based on a heirarchy of fields.
If the first field is empty, I want it to return the second, and if the second is empty, the third. I have tried the following but it only returns the first value.
If (IsEmpty (Field1 = 1) ; Field2;
If (IsEmpty (Field2 = 1); Field3; Field1))
I was able to get the first or third value to appear by using:
If (IsEmpty (Field1) &
If (IsEmpty (Field2); Field3; Field1))
But of course this doesn't show the Field2 at all.
Is there something along the lines of:
If (IsEmpty (Field1) &
If (IsEmpty (Field2); Field3; Field1, Field2))
which I can use? This obviously doesn't work because there are too many parameters in the function.
Any help would be very much appreciated! :-)
You need to nest your calc a bit more :
Case (
IsEmpty ( Field1 & Field2 ) ; Field3 ;
IsEmpty ( Field1 ) ; Field2 ;
Field1
)
In your examples, you had IsEmpty (Field1 = 1) which will test Field1=1, which is either True or False, but never empty. And the & is a concatentation operator, if you're wanting logical and then use and instead.
You could rewrite this in a more transparent way:
Case(
not isEmpty(Field1); Field1;
not isEmpty(Field2); Field2;
Field3
)
(this would be much easier to maintain/read in the future)