I'm trying to update a table and i want to runt 2 different SET senarios depending on a stock value.
Working CODE that does one senario.
UPDATE dbo.ar
SET webPublish = '0',
ArtProdKlass = '9999',
VaruGruppKod = '9999',
ItemStatusCode = '9' --Utgått ur sortimentet+
FROM tmp_9999
WHERE ar.ArtNr = tmp_9999.art AND ar.lagsadloartikel < '1'
What i would like to do is that IF last statement (ar.lagsaldoartikel) is >'1'Then i would like it to run this SET:
SET webPublish = '1',
ArtProdKlass = '1',
VaruGruppKod = '9999',
ItemStatusCode = '8'
So something like this i have tested:
IF AR.lagsaldoartikel < '1'
SET webPublish = '0',
ArtProdKlass = '9999',
VaruGruppKod = '9999',
ItemStatusCode = '9' --Utgått ur sortimentet+
FROM tmp_9999
WHERE ar.ArtNr = tmp_9999.art --Väljer ut artiklar som enbart finns i textfilen och har lagersaldo mindre än 1
ELSE
SET webPublish = '1',
ArtProdKlass = '1',
VaruGruppKod = '9999',
ItemStatusCode = '8' --Utgått ur sortimentet
FROM tmp_9999
WHERE ar.ArtNr = tmp_9999.art --Väljer ut artiklar som enbart finns i textfilen och har lagersaldo mindre än 1
Using CASE:
UPDATE dbo.ar
SET webPublish = '0',
ArtProdKlass = '9999',
VaruGruppKod = '9999',
ItemStatusCode = CASE WHEN AR.lagsaldoartikel < '1' THEN '9' ELSE '8' END
FROM tmp_9999
WHERE ar.ArtNr = tmp_9999.art
(If ItemStatusCode et al are numeric you should treat them as such.)
If is part of the procedural T-SQL. You can't use procedural statements inside the relational ones - the only way to use if would be to have two separate update statements, each in one branch of the if. However, that's a bad idea - it's not concurrency-safe.
One way to accomplish what you're trying to do is to use the case statement instead - that's just an expression, so it can be used in the set clause just fine:
set webPublish = case when AR.lagsaldoartikel < '1' then '0' else '1' end
(etc. for the other arguments).
However, I'd like to warn you - this is almost certainly a bad idea. It's probably going to back-fire on you soon in the future, when you realize that there's ten different conditions and a hundred different possible values you might want. Consider using a more idiomatically relational way of doing this - for example, taking the conditions and arguments from a different table - it's not necessary now, but if you ever find your conditions are expanding out of reasonable size, remember to consider changing the whole structure of the command if needed.
Related
I'm trying to build a query that searches based on a series of different criteria, however sometimes you will only have to use some of the criteria.
I'd like to be able to do something like below where, to change the query I would only need to change the bits in bold at the top of the query, so as only to search by criteria1 and criteria2 without having to change any of the rest of the query. Thanks
Declare #criteria1 as varchar(1),#criteria2 as varchar(1),#criteria3 as varchar(1)
Set #criteria1 = 'a'
Set #criteria2 = 'b'
Set criteria3 = '*'
/*I don't want to change anything below this point*/
Select * from table where
a = #criteria1
b = #criteria2
c = #criteria3
You can use conditional logic. If you want to use *, then:
Select *
from table
where (a = #criteria1 or #criteria1 = '*') and
(b = #criteria2 or #criteria2 = '*') and
(c = #criteria3 or #criteria3 = '*');
More typically, NULL would be used for this purpose -- because it works for any type and is not confused with any other "real" value:
Select *
from table
where (a = #criteria1 or #criteria1 is null) and
(b = #criteria2 or #criteria2 is null) and
(c = #criteria3 or #criteria3 is null);
Finally, SQL Server is going to do a full table scan in general with such conditions (the mixing of and and or). You might want to construct the query dynamically if you want the query to use indexes. However, if you are using one-character columns, then the indexes would not be particularly selective, so that might not apply in this particular case.
How I can remove only the first 0 character from a varchar?
For example '000303' ==> '00303'
I tried this without success, all the 0 characters are removed:
SELECT SUBSTRING('000303', PATINDEX('%[^0]%', '000303'),LEN('000303'));
Thanks
Try using STUFF Function
SELECT CASE WHEN LEFT('000303',1) = '0' THEN STUFF('000303',1,1,'') ELSE '000303' END
or Use RIGHT Function
SELECT CASE WHEN LEFT('000303',1) = '0' THEN RIGHT('000303', LEN('000303')-1) ELSE '000303' END
Instead of LEFT('000303',1) = '0' check you can also use
charindex('0','000303') = 1 or
'000303' LIKE '0%' (ughai suggestion)
Try this:
SELECT RIGHT(MyColumn, LEN(MyColumn) - 1)
This will remove the first character from the varchar column.
If it is specific to 0 then try this:
SELECT CASE WHEN LEFT(MyColumn,1) = '0'
THEN RIGHT(MyColumn, LEN(MyColumn) - 1)
ELSE
MyColumn END
Something like
SELECT CASE WHEN LEFT(Mycol,1) = '0' THEN SUBSTRING(MyCOL, 2, LEN(MyCOL)) END
I have a large SELECT INTO statement in a T-SQL script and currently I have two separate SELECT INTO's only differing by one OR condition in the WHERE clause. If my variable #cycle_nbr = 1 I have it doing one SELECT INTO, if #cycle_nbr = 0 I have it doing the other SELECT INTO.
I was wondering if there was a way to do this in one SELECT INTO with the #cylce_nbr condition in the WHERE itself.
Here is my WHERE clause:
WHERE ((a.gl_indicator = '0' OR a.gl_indicator = '1')
AND (a.gl_ins_type = '1' OR a.gl_ins_type = '3' )
AND rel_file_nbr is NULL
AND a.alpha_line NOT LIKE '%Z'
AND mis_process_dt >= #start_dt
and acctg_cyc_ym = #acctg_cyc)
OR (a.prem_sys_cd='T' AND acctg_cyc_ym = #acctg_cyc )
I only want this last condition OR (a.prem_sys_cd='T' AND acctg_cyc_ym = #acctg_cyc ) in there if #cycle_nbr = 1. Can I put an IF in there somewhere to make this work? Or do I have to stick with the IF(#cycle_nbr = 1) run this select ELSE run the other select?
Include your variable in the OR statement, i.e.,
OR (a.prem_sys_cd='T' AND acctg_cyc_ym = #acctg_cyc AND #cycle_nbr = 1)
I hope anyone can give any input to this problem. I have two exactly the same datasets, but one is larger than the other. Basically, I want to look to see if any variables in the smaller dataset (andrat_appen) have a certain value 'A'. If that is the case, I want to update the larger dataset ("andrat_APP_GENKORR", the exact same post, based on some ID-variables) with another value 'AG'.
If there are no values like 'A' in the variables in the smaller dataset, given the set if ID-variables, then nothing should happen to the same cells in the larger dataset.
Any suggestions on how to solve it?
UPDATE A
SET A.[ANDRAT_Vkod] = case when B.[ANDRAT_Vkod] = 'A' then 'AG' else A.[ANDRAT_Vkod] end,
A.[ANDRAT_timlon] = case when B.[ANDRAT_timlon] = 'A' then 'AG' else [ANDRAT_timlon] end
FROM [dbo].[andrat_APP_GENKORR] A
LEFT JOIN (SELECT EnhetsId, pnr, Etikett FROM [dbo].[andrat_appen]) B
ON A.EnhetsId = B.EnhetsId AND A.pnr = B.pnr AND A.Etikett = B.Etikett
Solved it! The solution is:
UPDATE A
SET A.[ANDRAT_Vkod] = (case when B.[ANDRAT_Vkod] = 'A' then 'AG' else A.[ANDRAT_Vkod] end),
A.[ANDRAT_timlon] = (case when B.[ANDRAT_timlon] = 'A' then 'AG' else A.[ANDRAT_timlon] end)
FROM [dbo].[andrat_APP_GENKORR] A
LEFT JOIN [dbo].[andrat_appen]) B
ON A.EnhetsId = B.EnhetsId AND A.pnr = B.pnr AND A.Etikett = B.Etikett
I have a big stored procedure, and basically I want to select all values (including null) if my variable #DimBrowserId is set to 0. I am using a case statement, however this is only catching values that actually have something and ignoring the NULL valued fields. Because I am using the = clause in the WHERE I cannot do IS NULL. I do not want to have to write 2 IF statements because the stored procedure would then be enormous, so I want to know how to get null values as well. Here is my code:
SELECT
DATEPART(yy, DATEADD(mi, #Mdelta, d.DimDateValue)),
DisableCount = COUNT(*)
FROM
dbo.FactDisable AS f
JOIN
dbo.DimDate AS d ON f.DimDateId = d.DimDateId
JOIN
dbo.DimDevice AS v ON f.DimDeviceId = v.DimDeviceId
WHERE
d.DimDateValue >= #StartDateGMT
AND d.DimDateValue <= #EndDateGMT
AND f.IsTest = #IncludeTest
AND f.DimProductId = #DimProductId
AND v.DimBrowserId = CASE
WHEN #DimBrowserId = 0 THEN v.DimBrowserId
ELSE #DimBrowserId
END
GROUP BY
DATEPART(yy, DATEADD(mi, #Mdelta, d.DimDateValue))
The code is near the CASE clause.
Thanks
Change that line to be
AND (#DimBrowserID = 0 OR #DimBrowserID = v.DimBrowserId)
If #DimBroserID is 0 then no filtering will be applied for this line.
Use ISNULL:
SELECT DATEPART(yy,DATEADD(mi,#Mdelta,d.DimDateValue)),
DisableCount=COUNT(*)
FROM dbo.FactDisable AS f
JOIN dbo.DimDate AS d ON f.DimDateId = d.DimDateId
JOIN dbo.DimDevice AS v ON f.DimDeviceId = v.DimDeviceId
WHERE d.DimDateValue >= #StartDateGMT AND d.DimDateValue <= #EndDateGMT
AND f.IsTest = #IncludeTest AND f.DimProductId = #DimProductId
AND v.DimBrowserId = CASE WHEN ISNULL(#DimBrowserId,0) = 0 THEN v.DimBrowserId ELSE #DimBrowserId END
GROUP BY DATEPART(yy,DATEADD(mi,#Mdelta,d.DimDateValue))
CASE WHEN COALESCE(#MightBeNull, 0) = 0 THEN ZeroResult ...
will be treated as zero if #MightBeNull is null, and whatever #MightBeNull is if it's not null.
Assuming null means any browser, a better data model for this scenario might be to set an ID that identifies any browser, instead of setting it to null.
You probably know what you are running into is NULL does not equal NULL in a comparison.
Assuming you don't have control of the data model to fix that, one option would be to coalesce your NULL values to an unused id.
The resulting WHERE clause would look like this, assuming -1 is the unused value you choose.
AND COALESCE(v.DimBrowserId, -1) = CASE WHEN #DimBrowserId = 0 THEN COALESCE(v.DimBrowserId, -1) ELSE #DimBrowserId END