I would like to do the following.
Update a field based on the value of another field like
update table set if(fielda=1){fieldb=2 fieldc=3}else{fieldd=2 fielde=3}
I know this is not valid mysql but its the best way for me to describe the problem.
update table set
b = case when a = 1 then 2 else b end,
c = case when a = 1 then 3 else c end,
d = case when a = 1 then d else 2 end,
e = case when a = 1 then e else 3 end
edit
according to your comment try this:
update table set
datefield_a = case when field_a = 1 then now() else datefield_a end,
datefield_b = case when field_a <> 1 then now() else datefield_b end
I think this syntax will achieve the result you attempted to specify.
UPDATE mytable
SET fieldb = CASE WHEN fielda = 1 THEN 2 ELSE fieldb END
, fieldc = CASE WHEN fielda = 1 THEN 3 ELSE fieldc END
, fieldd = CASE WHEN fielda = 1 THEN fieldd ELSE 2 END
, fielde = CASE WHEN fielda = 1 THEN fielde ELSE 3 END
The "trick" here is that we are updating all four columns, but in some "cases", we are assigning the current value of the column back to the column, resulting in no real change to the column value. (Once you get your mind bent around that idea, it's pretty easy.)
With MySQL, we do have a handy IF function (not available in most other RDBMS) that we can use to abbreviate that a bit, and achieve the same thing:
UPDATE mytable
SET fieldb = IF(fielda = 1, 2, fieldb)
, fieldc = IF(fielda = 1, 3, fieldc)
, fieldd = IF(fielda = 1, fieldd, 2)
, fielde = IF(fielda = 1, fielde, 3)
The pain is that you still have to repeat that same conditional test multiple times.
A single scan through the table (like these statements do), and getting all those assignments done in one fell swoop is going to be faster (and more efficient) than breaking this up and doing the assignments piecemeal using multiple statements.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Referring to a Column Alias in a WHERE Clause
SELECT
Trade.TradeId,
Isnull(Securities.SecurityType,'Other') SecurityType,
TableName,
CASE
WHEN
SecurityTrade.SecurityId IS NOT NULL
THEN
SecurityTrade.SecurityId
ELSE
Trade.SecurityId
END AS PricingSecurityID,
sum(Trade.Quantity)OVER(Partition by Securities.SecurityType, SecurityTrade.SecurityId,Trade.Price, Buy,Long ) as sumQuantity,
--added porfolio id for Getsumofqantity
Trade.PortfolioId,
Trade.Price,
case
when (Buy = 1 and Long = 1) then 1
when (Buy = 0 and Long = 0) then 1
else 0
end Position
from
Fireball_Reporting..Trade
where porfolioid =5 and Position =1
i want to use Position =1 in my where clause which is an alias of case
case
when (Buy = 1 and Long = 1) then 1
when (Buy = 0 and Long = 0) then 1
else 0
end Position
How can I use it in where clause?
I tried zo directly use that CASE statement in where clause, but failed.
WHERE Trade.SecurityId = #SecurityId AND PortfolioId = #GHPortfolioID AND
(case when (Buy = 1 and Long = 1) then 1 when (Buy = 0 and Long = 0) then 1 else 0 end Position = 1)
The SQL-Server docs says:
column_alias can be used in an ORDER BY clause, but it cannot be used in a WHERE, GROUP BY, or HAVING clause.
Similar in the MySQL doc it says:
Standard SQL disallows references to column aliases in a WHERE clause. This restriction is imposed because when the WHERE clause is evaluated, the column value may not yet have been determined.
In MySQL you can at least reuse aliases in the SELECT clause
You can't, not directly.
If you wrap the whole query in a sub-query, however, it works fine.
SELECT
*
FROM
(
SELECT
Trade.TradeId,
Isnull(Securities.SecurityType,'Other') SecurityType,
TableName,
CASE
WHEN SecurityTrade.SecurityId IS NOT NULL THEN SecurityTrade.SecurityId
ELSE Trade.SecurityId
END AS PricingSecurityID,
sum(Trade.Quantity)OVER(Partition by Securities.SecurityType,
SecurityTrade.SecurityId,Trade.Price, Buy,Long ) as sumQuantity,
--added porfolio id for Getsumofqantity
Trade.PortfolioId,
Trade.Price,
case
when (Buy = 1 and Long = 1) then 1
when (Buy = 0 and Long = 0) then 1
else 0
end Position
from
Fireball_Reporting..Trade
where
porfolioid = 5
)
AS data
WHERE
Position = 1
This means that you don't need to repeat the CASE statement in WHERE clause. (Maintainable and DRY).
It is also a structure that allows the optimiser to behave as if you had simply repeated yourself in the WHERE clause.
It's also very portable to other RDBMSs.
In SQL Server, then you also have another option...
SELECT
Trade.TradeId,
Isnull(Securities.SecurityType,'Other') SecurityType,
TableName,
CASE
WHEN SecurityTrade.SecurityId IS NOT NULL THEN SecurityTrade.SecurityId
ELSE Trade.SecurityId
END AS PricingSecurityID,
sum(Trade.Quantity)OVER(Partition by Securities.SecurityType,
SecurityTrade.SecurityId,Trade.Price, Buy,Long ) as sumQuantity,
--added porfolio id for Getsumofqantity
Trade.PortfolioId,
Trade.Price,
position.val AS Position
from
Fireball_Reporting..Trade
CROSS APPLY
(
SELECT
case
when (Buy = 1 and Long = 1) then 1
when (Buy = 0 and Long = 0) then 1
else 0
end AS val
)
AS position
where
porfolioid = 5
AND position.val = 1
You can't directly do this...but you can wrap an additional select around it all and use the where clause:
select * from
( SELECT
Trade.TradeId,
Isnull(Securities.SecurityType,'Other') SecurityType,
TableName,
CASE
WHEN
SecurityTrade.SecurityId IS NOT NULL
THEN
SecurityTrade.SecurityId
ELSE
Trade.SecurityId
END AS PricingSecurityID,
sum(Trade.Quantity)OVER(Partition by Securities.SecurityType, SecurityTrade.SecurityId,Trade.Price, Buy,Long ) as sumQuantity,
--added porfolio id for Getsumofqantity
Trade.PortfolioId,
Trade.Price,
case
when (Buy = 1 and Long = 1) then 1
when (Buy = 0 and Long = 0) then 1
else 0
end Position
from
Fireball_Reporting..Trade
where porfolioid =5 and Position =1
)x
where x.position = 1
I'm probably missing something but surely this will cover it:
WHERE (Buy = 1 and Long = 1) OR (Buy = 0 and Long = 0)
I would like to do the following.
Update a field based on the value of another field like
update table set if(fielda=1){fieldb=2 fieldc=3}else{fieldd=2 fielde=3}
I know this is not valid mysql but its the best way for me to describe the problem.
update table set
b = case when a = 1 then 2 else b end,
c = case when a = 1 then 3 else c end,
d = case when a = 1 then d else 2 end,
e = case when a = 1 then e else 3 end
edit
according to your comment try this:
update table set
datefield_a = case when field_a = 1 then now() else datefield_a end,
datefield_b = case when field_a <> 1 then now() else datefield_b end
I think this syntax will achieve the result you attempted to specify.
UPDATE mytable
SET fieldb = CASE WHEN fielda = 1 THEN 2 ELSE fieldb END
, fieldc = CASE WHEN fielda = 1 THEN 3 ELSE fieldc END
, fieldd = CASE WHEN fielda = 1 THEN fieldd ELSE 2 END
, fielde = CASE WHEN fielda = 1 THEN fielde ELSE 3 END
The "trick" here is that we are updating all four columns, but in some "cases", we are assigning the current value of the column back to the column, resulting in no real change to the column value. (Once you get your mind bent around that idea, it's pretty easy.)
With MySQL, we do have a handy IF function (not available in most other RDBMS) that we can use to abbreviate that a bit, and achieve the same thing:
UPDATE mytable
SET fieldb = IF(fielda = 1, 2, fieldb)
, fieldc = IF(fielda = 1, 3, fieldc)
, fieldd = IF(fielda = 1, fieldd, 2)
, fielde = IF(fielda = 1, fielde, 3)
The pain is that you still have to repeat that same conditional test multiple times.
A single scan through the table (like these statements do), and getting all those assignments done in one fell swoop is going to be faster (and more efficient) than breaking this up and doing the assignments piecemeal using multiple statements.
Trying to convert below query into SQL, query works fine on MySQL. Problem seems to be the CASE WHEN area field I get same error.
show Msg 102, Level 15, State 1, Line 44 Incorrect syntax near '='.
Msg 156, Level 15, State 1, Line 47 Incorrect syntax near the keyword
'AND'. Msg 156, Level 15, State 1, Line 49 Incorrect syntax near the
keyword 'ELSE'.
WHEN T.[StatusID] = 3
THEN
CASE WHEN (((SELECT COUNT(TA1.[Approver_ID]) FROM [QESTORM].[dbo].[CR_TicketApproval] TA1
INNER JOIN [QESTORM].[dbo].[CR_ControlFlow_SubRoute] CFSR1 ON TA1.[SubRoute_ID] = CFSR1.[ID]
WHERE TA1.[Ticket_ID]= #iTkID AND TA1.Active=1 AND CFSR1.Active=1 AND CFSR1.[Sequence] =(SELECT CFSR2.[Sequence] FROM [QESTORM].[dbo].[CR_Ticket] T2 INNER JOIN [QESTORM].[dbo].[CR_ControlFlow_SubRoute] CFSR2 ON T2.[SubRouteID] = CFSR2.[ID]
WHERE T2.[ID] = #iTkID))<(SELECT COUNT(DISTINCT CFSR1.[ID])FROM [QESTORM].[dbo].[CR_Ticket] AS T1 INNER JOIN [QESTORM].[dbo].[CR_ControlFlow_Route] AS CFR1 ON T1.[FormID] = CFR1.[FormID] INNER JOIN [QESTORM].[dbo].[CR_ControlFlow_SubRoute] AS CFSR1 ON CFR1.[ID] = CFSR1.[RouteID]
WHERE CFR1.[Active] = 1 AND CFSR1.[Active] = 1 AND T1.[ID] = #iTkID AND CFSR1.[Category] = 1 AND CFSR1.[Sequence] = ( SELECT CFSR2.[Sequence] FROM [QESTORM].[dbo].[CR_Ticket] AS T2 INNER JOIN [QESTORM].[dbo].[CR_ControlFlow_SubRoute] AS CFSR2 ON T2.[SubRouteID] = CFSR2.[ID]
WHERE T2.[ID] = #iTkID))))
THEN
CASE WHEN ((SELECT COUNT(1) FROM [QESTORM].[dbo].[CR_TicketApproval] WHERE [Ticket_ID]=#iTkID And [Active]=1) = 0)
THEN
--ERROR SHOW HERE => ((T.[AuditUser_ID] = '444' OR T.[AuditUser_ID] IS NULL) AND (nx.actor = 2 OR appSameSeq.NTLogin=in_NTLogin)
AND nx.actor=3
AND srSameSeq.subRouteID NOT IN (SELECT subRouteID FROM [QESTORM].[dbo].[CR_TicketApproval] WHERE [Ticket_ID]=#iTkID AND Active=1 )
AND appSameSeq.NTLogin=in_NTLogin
AND nx.actor=3 AND srSameSeq.subRouteID NOT IN (SELECT subRouteID FROM [QESTORM].[dbo].[CR_TicketApproval] WHERE [Ticket_ID] = #iTkID AND Active = 1)
ELSE 0
END
I'll toss my hat in the ring.
There may be more than one thing wrong with that SQL statement. What I'll point out is this:
CASE WHEN ((SELECT COUNT(1) FROM [QESTORM].[dbo]. [CR_TicketApproval] WHERE [Ticket_ID]=#iTkID And [Active]=1) = 0)
THEN
--ERROR SHOW HERE => ((T.[AuditUser_ID] = '444' OR T.[AuditUser_ID] IS NULL) AND (nx.actor = 2 OR appSameSeq.NTLogin=in_NTLogin)
AND nx.actor=3
AND srSameSeq.subRouteID NOT IN (SELECT subRouteID FROM [QESTORM].[dbo].[CR_TicketApproval] WHERE [Ticket_ID]=#iTkID AND Active=1 )
AND appSameSeq.NTLogin=in_NTLogin
AND nx.actor=3 AND srSameSeq.subRouteID NOT IN (SELECT subRouteID FROM [QESTORM].[dbo].[CR_TicketApproval] WHERE [Ticket_ID] = #iTkID AND Active = 1)
ELSE 0
END
Are you trying to evaluate a conditional expression, and return the result as a 1 or 0, as if it were a Boolean expression in a programming language?
That doesn't work in TSQL. This kind of expression evaluation:
SET #value = (1 > 0)
... will produce an error. You can't evaluate a conditional expression: you can only use it in a test, like in a WHERE, HAVING, or WHEN clause.
So, if that's what you're doing, you might do better to wrap your conditional evaluation in yet another CASE statement, like this:
THEN
CASE WHEN {complex conditional statement}
THEN 1
ELSE 0
END
ELSE
0
END
One other thing: this is an extremely complex query statement! I haven't analyzed it enough to see whether it could be simplified, but I'd suggest that you do so, with an eye toward using Common Table Expressions in place of some of your subqueries. This can make the query a lot easier to understand (and debug).
We are missing the complete query but it looks like you are opening too many parentheses.
If you look at the line where your error is shown:
((T.[AuditUser_ID] = '444' OR T.[AuditUser_ID] IS NULL) AND (nx.actor = 2 OR appSameSeq.NTLogin=in_NTLogin)
You are opening 2 parentheses but only close one.
That is why you get the error near else because you need to close that second parentheses before you can have an else
So you would need either
((T.[AuditUser_ID] = '444' OR T.[AuditUser_ID] IS NULL) AND (nx.actor = 2 OR appSameSeq.NTLogin=in_NTLogin))
or
(T.[AuditUser_ID] = '444' OR T.[AuditUser_ID] IS NULL) AND (nx.actor = 2 OR appSameSeq.NTLogin=in_NTLogin)
on that line
It looks like you don't have a 'return value' for your case statement on that specific line.
When you flatten your CASE WHEN statement you have something like this:
CASE WHEN <something> THEN
CASE WHEN <something else> THEN
CASE WHEN <something else again> THEN
-- THEN WHAT ?
ELSE
0
END
END
END
Instead of putting a value on the --THEN WHAT spot, you put another conditional statement. You have to select a value here.
I need to make a select like,
Select * from table WHERE column = x if column != -1
but i have no idea for now.
Anyone know or made in past something like that?
Thanks.
You should also write like this,
Select * from table
WHERE
1 = case when column != -1 then
case when column = x then 1 else 0 end
else 1 end
You can utilize case when in where clause.
Similarly you can add more conditional criteria like,
Select * from table
WHERE
1 = case when column != -1 then
case when column = x then 1 else 0 end
else 1 end
AND
1 = case when column1 [conditional operator] value then
case when column1 = xx then 1 else 0 end
else 1 end
This is just an example how you can integrate more conditional criteria together, even though you can add more case when in else part even.
Working on a view that pulls from two table however in one table I need to select either one field or another depending on a third..it's the if else that has me stubbed.
Create view as
select
pens.PartNo,
pens.Title,
ranges.weight
if(pens.SpeacialOffer = 1 then pens.offer as Price else pens.Price)
from
pens, ranges
where
pens.penrange = ranges.id;
If the specialoffer is falged the the view needs to pull in the offer else it needs to pull in the Price.
What you need is a CASE operator:
CASE
WHEN condition
THEN value_a
ELSE value_b
END
So in your case:
CASE
WHEN pens.SpeacialOffer = 1
THEN pens.offer
ELSE pens.price
END
This replaces the entire column definition in your SELECT statement, so the whole view becomes:
Create View as
Select
pens.PartNo,
pens.Title,
ranges.weight,
Case
When pens.SpeacialOffer = 1
Then pens.offer
Else pens.price
End as Price
From
pens, ranges
Where
pens.penrange = ranges.id;
Use CASE, also converted the query to explicit join instead of implicit join
select pens.PartNo,
pens.Title,
ranges.weight,
(Case when
pens.SpeacialOffer = 1 then
pens.offer else pens.Price
end ) as Price
FROM pens,
JOIn ranges
ON pens.penrange = ranges.id;
Here's one way:
Create view as select
pens.PartNo,
pens.Title,
ranges.weight,
(pens.SpeacialOffer * pens.offer + (1 - pens.SpeacialOffer) * pens.price) as Price
from
pens,
ranges
where
pens.penrange = ranges.id;