Convert IIF statement from access to T-SQL SQL Server(Pass-Through) - sql-server

I have an update query that I created it in Access 2013. I have a table with over 1.5 million records, I am trying to run an update query but it takes forever sometimes especially if I am updating thousands of rows. So I figured out that I would use pass through option in access but when I try to do that I get a syntax error in my query as the syntax is different in access than it is in SQL Server. How could I convert my query to sql server so my queries won't take forever to run.
Here is my original access query that I want to convert it to T-SQL.
UPDATE CLAIM
INNER JOIN 06 ON [06].ID = Claim.ID
SET reason_code_01= IIF(reason_code_01 is null,”06”,reason_code_01), reason_code_02= IIF(reason_code_01 <> null,”06”,reason_code_02), reason_code_03= IIF(reason_code_01 <> null,”06”,reason_code_03), reason_code_04= IIF(reason_code_01 <> null,”06”,reason_code_04),overpaid_deduc= IIF(overpaid_deduc is null,[06].[DED AMT],overpaid_deduc), overpaid_deduc2= IIF(overpaid_deduc <>null,[06].[DED AMT],overpaid_deduc2),overpaid_deduc3= IIF(overpaid_deduc <> null,[06].[DED AMT],overpaid_deduc3),overpaid_pay1= IIF(overpaid_pay1 is null,[06].[PAY 1],overpaid_pay1),overpaid_pay2= IIF(overpaid_pay1 <> null,[06].[PAY 1],overpaid_pay2),overpaid_pay3= IIF(overpaid_pay1 <> null,[06].[PAY 1],overpaid_pay3)
WHERE ((([06].sort_order)=1));

Your syntax is off a bit for updates with joins. And you need to use a case statement instead of iif. Here is a condensed version which should help:
UPDATE c
SET reason_code_01=
case when reason_code_01 is null
then '06'
else reason_code_01
end,
...
overpaid_pay3=
case when overpaid_pay1 is not null
then [06].[PAY 1]
else overpaid_pay3
end
FROM CLAIM c
INNER JOIN 06 ON [06].ID = c.ID
WHERE [06].sort_order=1

Related

SQL Server - Multiple select queries hit performance

Recently I ran into an issue where we have multiple concurrent client requests causing performance issue in db. I tried the test scenario and as it turned out, when I run SELECT queries (same query) 6 to 7 times (gets worse with more), It degrades the performance and execution takes a lot of time. However I tried this one
SELECT TOP (100) COUNT(DISTINCT([Doc_Number])) AS "Expression"
FROM (
SELECT *
FROM "dbo"."Dummy_Table" "table_alias"
WHERE ((CAST("table_alias"."ID" AS NVARCHAR)) NOT IN
(
SELECT "PrimaryKey" AS ExceptionKey
FROM dbo.exceptions inner_exceptionStatus
LEFT JOIN dbo.Workflow inner_workflowStates ON
(inner_exceptionStatus."Status"= inner_workflowStates."UUID" AND
inner_exceptionStatus."UUID"= 'CA1662D6-73A2-4692-A765-E7E3EDB66062')
WHERE ("inner_workflowStates"."RemoveFromRecordSet" = 1 AND
"inner_workflowStates"."IsDeleted" = 0) AND
("inner_exceptionStatus"."IsArchived" IS NULL OR
"inner_exceptionStatus"."IsArchived" = 0)))) wrapperQuery
The query when runs alone takes around 1sec execution time. But If we runs it in parallel, for each query it takes up a wried amount of time of leads to timeout.
The only thing bothers me here is that SELECT query should be non-blocking and even with shared lock, then need to get along easily.
I am not sure if there is anything wrong in the query that adds up the situation.
Any help is deeply appreciated !!
Try this way
SELECT Count(DISTINCT( [Doc_Number] )) AS Expression
FROM dbo.Dummy_Table table_alias
WHERE NOT EXISTS (SELECT 1
FROM dbo.exceptions inner_exceptionStatus
INNER JOIN dbo.Workflow inner_workflowStates
ON ( inner_exceptionStatus.Status = inner_workflowStates.UUID
AND inner_exceptionStatus.UUID = 'CA1662D6-73A2-4692-A765-E7E3EDB66062' )
WHERE inner_workflowStates.RemoveFromRecordSet = 1
AND inner_workflowStates.IsDeleted = 0
AND ( inner_exceptionStatus.IsArchived IS NULL
OR inner_exceptionStatus.IsArchived = 0 )
AND table_alias.ID = PrimaryKey)
Made couple of changes.
Changed NOT IN to NOT EXISTS
Removed the convert in "table_alias"."ID" because it will avoid using any index present in "table_alias"."ID" column. If the conversion is really required then add it.
Removed Top (100) since there is no Group By it will return a single record as result.
Still if the query is running slow then you need to post the execution plan and make sure the statistics are up-to-date
You can simplyfy your query like this :
SELECT COUNT(DISTINCT(Doc_Number)) AS Expression
FROM dbo.Dummy_Table dmy
WHERE not exists
(
SELECT *
FROM dbo.exceptions ies
INNER JOIN dbo.Workflow iws ON ies.Status= iws.UUID AND ies.UUID= 'CA1662D6-73A2-4692-A765-E7E3EDB66062'
WHERE iws.RemoveFromRecordSet = 1 AND iws.IsDeleted = 0 AND (ies.IsArchived IS NULL OR ies.IsArchived = 0)
and dmy.ID=PrimaryKey
)
Like prdp say :
Changed NOT IN to NOT EXISTS
Removed the convert in "table_alias"."ID" because it will avoid using any index present in "table_alias"."ID" column. If the conversion is really required then add it.
Removed Top (100) since there is no Group By it will return a single record as result.
I add :
Remove you temporary table wrapperQuery
You can use INNER JOIN because into where you test RemoveFromRecordSet = 1 then you remove null values.
Remove not utils quotes ,brackets and parenthèses into where clause

Joins and linked servers query causing delay

Hey guys the code below is taking a really long time. I've been looking at it for quite a while. Is there anything that stands out as the obvious cause of delay?
[SQLSRV-3-JB] is a linked server BTW
Select count(cast (Unique_ID as bigint)) as [Count],
T.[Region_Code],
T.[Region_Name],
U.[Region_Code],
Y.[Examination_Year],
case when [Subject] = 'MUSIC THEORY' THEN 'Theory'
else 'Practical'
end
from [SQLSRV-3-JB].[X].[dbo].[Exam_and_Candidate_Details] Y
left join [SQLSRV-3-JB].[X].[dbo].[UK_Exam_Centre_Info] T
on Y.Centre_Code = T.Centre_Code
left join [SQLSRV-3-JB].[X].[dbo].[UK_Exam_Centres] U
on Y.Centre_Code = U.Centre_Code
where Y.[Examination_Year] between 2010 and 2016
group by Y.[Examination_Year],
T.[Region_Code],
T.[Region_Name],
U.[Region_Code],
case when [Subject] = 'MUSIC THEORY' THEN 'Theory'
else 'Practical'
end
Yes, there is one very obvious problem - the remote server. When you use a linked server like this, SQL Server has a disturbing habit of pulling all of the data in the remote tables to the local server before performing JOINs or filtration.
The correct way to handle this is to make this query a view on the remote server, and query the view with your WHERE clause on your end. So, your remote code would look like this:
-- Remote Server
USE X
GO
CREATE VIEW dbo.ExamCenterInfo
AS
Select count(cast (Unique_ID as bigint)) as [Count],
T.[Region_Code],
T.[Region_Name],
U.[Region_Code],
Y.[Examination_Year],
case when [Subject] = 'MUSIC THEORY' THEN 'Theory'
else 'Practical'
end
from dbo.[Exam_and_Candidate_Details] Y
left join dbo.[UK_Exam_Centre_Info] T
on Y.Centre_Code = T.Centre_Code
left join dbo.[UK_Exam_Centres] U
on Y.Centre_Code = U.Centre_Code
group by Y.[Examination_Year],
T.[Region_Code],
T.[Region_Name],
U.[Region_Code],
case when [Subject] = 'MUSIC THEORY' THEN 'Theory'
else 'Practical'
end
Then your local code:
-- Local Server
SELECT *
FROM [SQLSRV-3-JB].[X].[dbo].ExamCenterInfo ECI
where ECI.[Examination_Year] between 2010 and 2016
NOTE: There is some possibility that this will pull all of the view output before filtering by year. If this is still a problem, you will have to create a more complex mechanism to execute the view with filtration on the remote server.

Moving Access update query to SQL server

We are migrating a Access database to Azure, one update queries is not working despite trying several syntax changes and removals of spaces.
Below is the design view of the query in Access:
Query Design
The following is the SQL expression of the update query in Access:
UPDATE SPEND_steve, KeywordRULES
SET SPEND_steve.Category = [KeywordRULES].Category
WHERE (((SPEND_steve.Category) Is Null) AND ((SPEND_steve.ItemDescription) Like "*"
And (SPEND_steve.ItemDescription)=[KeywordRULES].[ItemDescription]
And (SPEND_steve.ItemDescription) Like "*"));
With the above I receive error 102: Incorrect syntax near ','.
Thank you in advance for any help to move this functioning query from Access to SQL server!!!
Try removing ", KeywordRULES" from Line 1, an UPDATE statement is only able to update one table (or view) at a time.
UPDATE SPEND_steve
SET SPEND_steve.Category =
[KeywordRULES].Category WHERE (((SPEND_steve.Category) Is Null) AND
((SPEND_steve.ItemDescription) Like "" And (SPEND_steve.ItemDescription)=
[KeywordRULES].[ItemDescription] And (SPEND_steve.ItemDescription) Like "")) ;
SQL Update syntax is a bit different to Access, in that each update statement should affect a single table. You can however reference other tables through a join or other ways depending on what you are trying to do.
So KeywordRules is implicitly joined in your query. So your intention is to update the SPEND_steve table based on info from the KeywordRules table. You can do this by a join to the keyword rules.
Update SPEND_steve
Set SPEND_steve.Category = [KeywordRULES].Category WHERE
(((SPEND_steve.Category) Is Null) AND ((SPEND_steve.ItemDescription) Like ""
And (SPEND_steve.ItemDescription) Like ""))
JOIN KeywordRules on (SPEND_steve.ItemDescription)=[KeywordRULES].[ItemDescription];
Also you should change like "" to = "" which may yeild a performance increase, although you might want to check for AND IS Not NULL as well if it could be null.

Update on linked server with nested subquery

I want to update on a linked server the result of a query as well from a linked server.
The first sql snippet gives me the value to be updated:
SELECT mmdb_vessel.IMONo, mmdb_vessel.DeathDate
From OPENQUERY(MMDB, 'SELECT FunctionalLocation, IMONo, VesselStatus, CONVERT(VARCHAR(10), DeathDate, 102) AS DeathDate
FROM VESSEL
WHERE VESSEL.VesselStatusID <> 42 AND VESSEL.DeathDate is not null') as mmdb_vessel
, eb_all_v
WHERE
eb_all_v.IMO_No = mmdb_vessel.IMONo
AND eb_all_v.status = 'in service'
the second is actually what I'm not able to implement, it should show what I want to achieve:
UPDATE EPI2..EPI.PLANT
SET KIND_OF_LIQUIDATION_NO = 1
, LIQUIDATION_DATE = [result from snippet above].DeathDate
Where EPI2..EPI.PLANT.IMONo = [result from snippet above].IMONo
I'm not so sure if my explanation is sufficient, please feel free to ask for additional information!
Thanks, already in advance,
Werner
I would recommend to select the data from the remote server first and store the required data e.g. in a temptable, because LinkedServer and updates can have some sideeffects (e.g. performing a tablescan on the remote table, altough you would not expect it if an updaet is involved, etc) - but this depends on your exact usage/scenario.
Select data you need to update
SELECT * INTO #tmpTable FROM LINKEDSERVER.EPI.dbo.PLANT WHERE ....
Perform the update on local server
UPDATE EPI2..EPI.PLANT SET KIND_OF_LIQUIDATION_NO = 1, LIQUIDATION_DATE = t.DeathDate FROM #tmpTable t INNER JOIN EPI2..EPI.PLANT p on t.IMONo = p.IMONo

How to do Sql Server CE table update from another table

I have this sql:
UPDATE JOBMAKE SET WIP_STATUS='10sched1'
WHERE JBT_TYPE IN (SELECT JBT_TYPE FROM JOBVISIT WHERE JVST_ID = 21)
AND JOB_NUMBER IN (SELECT JOB_NUMBER FROM JOBVISIT WHERE JVST_ID = 21)
It works until I turn it into a parameterised query:
UPDATE JOBMAKE SET WIP_STATUS='10sched1'
WHERE JBT_TYPE IN (SELECT JBT_TYPE FROM JOBVISIT WHERE JVST_ID = #jvst_id)
AND JOB_NUMBER IN (SELECT JOB_NUMBER FROM JOBVISIT WHERE JVST_ID = #jvst_id)
Duplicated parameter names are not allowed. [ Parameter name = #jvst_id ]
I tried this (which i think would work in SQL SERVER 2005 - although I haven't tried it):
UPDATE JOBMAKE
SET WIP_STATUS='10sched1'
FROM JOBMAKE JM,JOBVISIT JV
WHERE JM.JOB_NUMBER = JV.JOB_NUMBER
AND JM.JBT_TYPE = JV.JBT_TYPE
AND JV.JVST_ID = 21
There was an error parsing the query. [ Token line number = 3,Token line offset = 1,Token in error = FROM ]
So, I can write dynamic sql instead of using parameters, or I can pass in 2 parameters with the same value, but does someone know how to do this a better way?
Colin
Your second attempt doesn't work because, based on the Books On-Line entry for UPDATE, SQL CE does't allow a FROM clause in an update statement.
I don't have SQL Compact Edition to test it on, but this might work:
UPDATE JOBMAKE
SET WIP_STATUS = '10sched1'
WHERE EXISTS (SELECT 1
FROM JOBVISIT AS JV
WHERE JV.JBT_TYPE = JOBMAKE.JBT_TYPE
AND JV.JOB_NUMBER = JOBMAKE.JOB_NUMBER
AND JV.JVST_ID = #jvst_id
)
It may be that you can alias JOBMAKE as JM to make the query slightly shorter.
EDIT
I'm not 100% sure of the limitations of SQL CE as they relate to the question raised in the comments (how to update a value in JOBMAKE using a value from JOBVISIT). Attempting to refer to the contents of the EXISTS clause in the outer query is unsupported in any SQL dialect I've come across, but there is another method you can try. This is untested but may work, since it looks like SQL CE supports correlated subqueries:
UPDATE JOBMAKE
SET WIP_STATUS = (SELECT JV.RES_CODE
FROM JOBVISIT AS JV
WHERE JV.JBT_TYPE = JOBMAKE.JBT_TYPE
AND JV.JOB_NUMBER = JOBMAKE.JOB_NUMBER
AND JV.JVST_ID = 20
)
There is a limitation, however. This query will fail if more than one row in JOBVISIT is retuned for each row in JOBMAKE.
If this doesn't work (or you cannot straightforwardly limit the inner query to a single row per outer row), it would be possible to carry out a row-by-row update using a cursor.

Resources