Why is alias not allowed in GROUP BY in MySQL? [duplicate] - mysql

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)

Related

How to update a record conditionally with a field value in the same record in MySQL? [duplicate]

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.

using if statement in mysql query

I would like to use if statement in sql query :
what I want :
if(tractions_delivery.send_date_id !=0 ){
date_send_commodities.id = tractions_delivery.send_date_id
}
my query :
from
tractions_delivery,user_address,province,city,date_send_commodities,users
WHERE
tractions_delivery.tr_id = $tr_id
AND
tractions_delivery.address_id = user_address.id
AND
user_address.province_id = province.id
AND
user_address.city_id = city.id
AND
//not work
(tractions_delivery.send_date_id IS NOT 0 date_send_commodities.id = tractions_delivery.send_date_id)
AND
users.id = user_address.user_id
You could use the CASE-statement
SELECT
*
FROM
tractions_delivery,
user_address,
province,
city,
date_send_commodities,users
WHERE
tractions_delivery.tr_id = $tr_id AND
tractions_delivery.address_id = user_address.id AND
user_address.province_id = province.id AND
user_address.city_id = city.id AND
CASE WHEN tractions_delivery.send_date_id != 0 THEN date_send_commodities.id = tractions_delivery.send_date_id ELSE 1=1 END AND
users.id = user_address.user_id
You can only use if statements in stored procedures or functions. If you just write a sql statement unfortunately you cannot use if statements around the query. But you can use logic in the query itself, e.g.:
SELECT CASE WHEN col1 = col2 THEN'col1 equals col2' else 'col1 doesnt equal col2' ELSE
FROM table1
So around doesnt work, but in the field list you can create CASE WHEN ELSE END logic.
CASE or IF() operators can be of help.
Examples,
SELECT (CASE 1 WHEN 1 THEN 'One' WHEN 2 THEN 'Two' ELSE 'More' END) 'Result';
OR
SELECT IF(1=1, 'One', 'Two') 'Result';
These CASE and IF() operators can be used in the SELECT clause to conditionally interpret column values and return in the resultset.
Note: Do not confuse CASE operator here with 'CASE conditional syntax block' that ends with END CASE.

Error in nested case query using SQL

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.

Select * from table WHERE `column` = x if `column` != -1

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.

Update Query based on condition

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.