merge condition is not working in sql server - sql

I have two tables one is (providerLoc) and another one is (tmpProviderLoc) I need to take three columns combination from tmpProviderLoc and need to check the records exist in ProviderLoc
Case 1 : If record exist in providerLoc i need to update another column(Npi) in providerLoc based on column (npi) in tmpProviderLoc
case 2 : if not exist i need to insert the values in providerLoc
for that I have written below query:
MERGE INTO [dbo].[ProviderLoc] AS PL
USING
(
select *
from (
select *,
row_number() over (partition by [Location_ID],[PProviderTaxID]
,[POBOXZIP] order by [Location_ID],[PProviderTaxID],[POBOXZIP]) as row_number
from [dbo].[TmpProviderLoc]
) as rows
where row_number = 1
) AS TPL
ON TPL.[Location_ID] = PL.[ecProviderID]
AND TPL.[PProviderTaxID] = PL.[TaxID]
AND TPL.[NPI] = PL.[NPI]
AND TPL.[POBOXZIP] = PL.[POBOXZIP]
WHEN MATCHED THEN
UPDATE SET PL.[NPI] = CASE
WHEN TPL.[NPI] = NULL THEN PL.[NPI]
ELSE TPL.[NPI]
END
WHEN NOT MATCHED THEN
INSERT (EcProviderID,TaxID,NPI,POBOXZIP,ProviderLocationStatusID,CreatedON)
VALUES (TPL.[Location_ID],TPL.[PProviderTaxID],TPL.[NPI]
,TPL.[POBOXZIP],1,GETDATE());
But I am failing in updating the NPI value -- if npi value is new in tmpProviderLoc it is not updating in ProviderLoc..
Could any one please look into this issue..
or any other way to go through this kind of checking

The equal symbol in this is incorrect: WHEN TPL.[NPI] = NULL THEN PL.[NPI]
Use IS NULL
WHEN TPL.[NPI] IS NULL THEN PL.[NPI]
NULLs are special. They are "indeterminate" so they cannot be equal or unequal to anything purely because they just cannot have any value "determined". NULLs are the absence of value and equal/unequal does not apply.
To discover if NULL exists use IS NULL - or - IS NOT NULL to discover if there is a non-null value.

Related

Deduplicate table while keeping the version vers column is not null

I have a table with 2 columns: an id and an associated label.
Example:
id1,label1
id1,null
id2,label2
id3,null
I would like to deduplicate on the 1st column to keep the version where the label column is not null. But if the id appears only once, I want to keep the line no matter what, even though the label is null.
The output I would want with the example is:
id1,label1
id2,label2
id3,null
How can I do this ?
Consider below (BigQuery)
select *
from your_table
qualify 1 = row_number() over(partition by id order by label desc)
if applied to sample data in your question - output is
Use EXISTS (see demo)
delete
from <table1> d1
where d1.label is null
and exists ( select null
from <table1> d2
where d2.id = d1.id
and d2.label is not null
) ;
EXISTS always returns True or False if the subslect would have returned at least 1 row. In this case it returns True only when there is a matching row where label is not null.
Note: This does not work where there are multiple id each having a non-null label nor each having a null label. So would not work on tuples
('a',null) with ('a',null) nor the tuples
('a','l1') with ('a','l1')

SQL Query : should return Single Record if Search Condition met, otherwise return Multiple Records

I have table with Billions of Records, Table structure is like :
ID NUMBER PRIMARY KEY,
MY_SEARCH_COLUMN NUMBER,
MY_SEARCH_COLUMN will have Numeric value upto 15 Digit in length.
What I want is, if any specific record is matched, I will have to get that matched value only,
i.e. : If I enter WHERE MY_SEARCH_COLUMN = 123454321 and table has value 123454321 then this only should be returned.
But if exact value is not matched, I will have to get next 10 values from the table.
i.e. : if I enter WHERE MY_SEARCH_COLUMN = 123454321 and column does not have the value 123454321 then it should return 10 values from the table which is greater than 123454321
Both the case should be covered in single SQL Query, and I have have to keep in mind the Performance of the Query. I have already created Index on the MY_SEARCH_COLUMN columns, so other suggestions are welcome to improve the Performance.
This could be tricky to do without using a proc or maybe some dynamic SQL, but we can try using ROW_NUMBER here:
WITH cte AS (
SELECT ID, MY_SEARCH_COLUMN,
ROW_NUMBER() OVER (ORDER BY MY_SEARCH_COLUMN) rn
FROM yourTable
WHERE MY_SEARCH_COLUMN >= 123454321
)
SELECT *
FROM cte
WHERE rn <= CASE WHEN EXISTS (SELECT 1 FROM yourTable WHERE MY_SEARCH_COLUMN = 123454321)
THEN 1
ELSE 10 END;
The basic idea of the above query is that we assign a row number to all records matching the target or greater. Then, we query using either a row number of 1, in case of an exact match, or all row numbers up to 10 in case of no match.
SELECT *
FROM your_table AS src
WHERE src.MY_SEARCH_COLUMN = CASE WHEN EXISTS (SELECT 1 FROM your_table AS src2 WITH(NOLOCK) WHERE src2.MY_SEARCH_COLUMN = 123456321)
THEN 123456321
ELSE src.MY_SEARCH_COLUMN
END

Selecting from table to insert into another, getting a type error

I have the following query which inserts data into one table after selecting it from another.
The problem is that the data types do not match for one of the columns. I have simplified the query below.
INSERT INTO tbl.LogTable (
[SelPartNo], -- This does not match, see below
)
SELECT TOP 1
IF([SelPartNo] = 'False', NULL, [SelPartNo],
FROM tbl.MyTable
WHERE ID = '20358'
ORDER BY CreateDate DESC
The first SelPartNo is an int and the second is a VarChar. In most instances the SelPartNo for the second one (tbl.MyTable) is NULL or an integer, which I don't think will cause a problem. But in some cases the value is "False", which needs to return NULL.
I have tried an IF statement but I am doing something wrong because it's giving a syntax error and I am unsure if this is the correct approach.
Your code is syntactically incorect...
Try it with
NULLIF([SelPartNo],'False')
This function returns NULL if the two expressions are equal.
Details: https://msdn.microsoft.com/en-us/library/ms177562.aspx
I don't think IF is a function, at least not one which you can use in a SELECT statement. But CASE WHEN ... END is your friend:
INSERT INTO tbl.LogTable (
[SelPartNo]
)
SELECT TOP 1
CASE WHEN [SelPartNo] = 'False' THEN NULL ELSE [SelPartNo] END
FROM tbl.MyTable
WHERE ID = '20358'
ORDER BY CreateDate DESC

Is a subquery, which is returning no row, equal to NULL?

In SQL Server, if my SELECT statement in a subquery returns no row, is then the result of the subquery equal to NULL? I made some research, but I am not sure about it.
Example:
IF (SELECT TOP 1 CLMN1 FROM SOMETABLE) IS NOT NULL THEN
....
I am asking to understand the behaviour of the if-statement above.
Looks like the answer is yes:
DECLARE #Test TABLE (Id INT)
INSERT INTO #Test VALUES (1)
SELECT * FROM #Test WHERE Id = 2
SELECT CASE WHEN (SELECT * FROM #Test WHERE Id = 2) IS NULL THEN 1 ELSE 0 END
EDIT: after you updated your question I think I should add that instead of checking if there are rows with IS NULL you should use the following that can be better optimised by the server:
IF EXISTS(SELECT * FROM #Test WHERE Id = 2)
BEGIN
-- Whatever
END
NULL means no value, for example that the "box" for a certain column in a certain row is empty. NO ROW means that there are no rows.
No, NULL is a column value that indicates that the value of that column for a given row has no valid value. There would have to be a row returned by your query for that row to contain NULL column values.
A query that returns no rows just means that no rows matched the predicate you used in the query and therefore no data was returned at all.
Edit: After the question was edited, my answer doesn't address the specific case called out in the question. Juan's answer above does.

SELECT refering value to sub query

I am trying to get a random id value from my table. The condition is that the selected value must not exist for the same id and different language (language is lang field)
I do this:
SELECT id_v as p,cont FROM value_phrase WHERE lang=1 AND
NULL IN (SELECT cont FROM value_phrase WHERE id_v=p AND lang=2)
ORDER BY RAND() LIMIT 0,1
... but I do not get any results (It must be an error in my query, because there are many rows satisfying the desired condition.) How should I fix it?
-- SOLVED --
the solution is to use NOT EXISTS instead of NULL IN, and use table aliases to refer the first id_v into the sub query. This way (thanks to Mark Byers):
SELECT first.id_v, first.cont
FROM value_phrase AS
FIRST WHERE lang =1
AND NOT
EXISTS (
SELECT cont
FROM value_phrase
WHERE id_v = first.id_v
AND lang =2
)
ORDER BY RAND( )
LIMIT 0 , 1
If you want to check if a value does not exist, use NOT EXISTS.
AND NOT EXISTS (SELECT ... )
Your condition NULL IN (...) will never return anything, because a comparison with NULL always returns NULL and that is treated as "false" in a query condition.