CASE inside IF() function in raw SQL query - mysql

I have a SQL query which already uses an IF() function to check some conditions on basis of which respective expression is returned. I have to add another condition (which will be another 'and') inside the IF() which will affect the attributes from both the expressions. The query is,
select
#{booking_variable}.travel_id as operator_id,
round(sum(#{ticket_variable}.customer_commission), 2) as commission,
IF(
(#{booking_variable}.is_online = #{AdminType::YES}
and #{booking_variable}.is_ts_payment = #{AdminType::YES}),
round(sum(-#{ticket_variable}.customer_commission
- #{ticket_variable}.convenience_charge_amount
+ #{ticket_variable}.our_convenience_charge_amount), 2),
round(sum(#{ticket_variable}.adult_fare
- #{ticket_variable}.customer_commission
+ #{ticket_variable}.service_tax_amount
+ #{ticket_variable}.our_convenience_charge_amount
- #{ticket_variable}.offer_discount), 2)
) as amount_to_be_paid,
round(sum(#{booking_variable}.total_fare)) as total_fare,
0 as cancel_fare,
round(sum(#{ticket_variable}.adult_fare
+ #{ticket_variable}.service_tax_amount
- #{ticket_variable}.offer_discount )) as net_amount,
#{booking_variable}.travel_name as operator_name,
ROUND(sum(#{ticket_variable}.service_tax_amount), 2) as total_service_tax,
ROUND(sum(#{ticket_variable}.convenience_charge_amount), 2) as total_convenience_charge_amount,
ROUND(sum(#{ticket_variable}.our_convenience_charge_amount), 2) as total_our_convenience_charge_amount,
0 as cancelled_convenience_charge_amount,
(select users.branch_id from users where id=#{ticket_variable}.booked_by) as travel_branch_id
from #{booking_variable} use index(index_#{booking_variable}_travel_date),
#{ticket_variable}
where #{conditions1[0]}
group by travel_branch_id, operator_id
Here, inside the IF() expression, I have to check another variable's value . If the value is true, then the query should run as is, if not, the value of #{ticket_variable}.convenience_charge_amount + #{ticket_variable}.our_convenience_charge_amount and #{ticket_variable}.our_convenience_charge_amount is to be taken as 0.
Any help appreciated.

You can nest IF() expressions.
If you need part of your calculation to be conditional, you can use an IF() for that.
...
IF(
(#{booking_variable}.is_online = #{AdminType::YES}
and #{booking_variable}.is_ts_payment = #{AdminType::YES}),
round(sum(-#{ticket_variable}.customer_commission
- IF((...some other condition...),
#{ticket_variable}.convenience_charge_amount
+ #{ticket_variable}.our_convenience_charge_amount,
0)
), 2),
...

Related

Using case statement or IF inside a WHERE clause

I have several stored procedures that are almost identical but have some different AND parts inside a WHERE clause.
Based on a variable deptname, I want to add additional AND/OR conditions to my already existing WHERE clause. So kind of like IF/CASE WHEN on the part that is different.
Think about it as string concatenation
query_string = 'WHERE a= XYZ AND B= 123"
if deptname = a: query_string + "AND additional conditions for dept a"
else if deptname = b:query_string + "AND additional conditions for dept b"
What is the appropriate way to use a variable?
here is some pseudo code of what I am trying to do
SELECT
personID AS pid,
personcode,
persondeptcode,
more_fields AS fields
FROM
TABLE_XYZ
WHERE
--shared parts
personcode = 'C'
AND
persondeptcode = 'MAJ'
--- NOW the different part
IF #deptname = "deptA"
AND
(
PROGRAM_LDESCR IN
(
'prog1',
'prog2',
'prog3'
)
OR
aprogram IN ('aprogram1')
OR
(aprogram IN ('aprogram2') AND PLAN_LDESCR IN ('plan123'))
);
--- THIS IS A DIFFERENT DEPT SO WE HAVE DIFFERENT AND PART
ELSE IF #deptname = "deptB"
(
PROGRAM_LDESCR IN
(
'1234'
)
OR
aprogram IN ('a1234')
);
You can use a CASE expression in this case, the important thing is to make sure you have an ELSE clause to ensure the expression remains true if #deptname is not one of the two values with extra conditions:
WHERE personcode = 'C'
AND persondeptcode = 'MAJ'
AND (CASE #deptname
WHEN "deptA" THEN PROGRAM_LDESCR IN ('prog1', 'prog2', 'prog3')
OR aprogram IN ('aprogram1')
OR aprogram IN ('aprogram2') AND PLAN_LDESCR IN ('plan123')
WHEN "deptB" THEN PROGRAM_LDESCR IN ('1234')
OR aprogram IN ('a1234')
ELSE 1
END)
Here is a simple demo of a CASE expression used in this fashion.
You seem to want something like:
AND
(#deptname = 'dept123' AND (PROGRAM_LDESCR IN ('1234') OR aprogram IN ('a1234')) OR
#deptname <> 'dept123'
)
To combine the last part of the WHERE clause (if I'm understanding your commented-code correctly), you could do something like the following:
SELECT
personID AS pid,
personcode,
persondeptcode,
more_fields AS fields
FROM
TABLE_XYZ
WHERE
personcode = 'C'
AND persondeptcode = 'MAJ'
AND (
(#deptname="deptA" AND (PROGRAM_LDESCR IN ('prog1', 'prog2', 'prog3') OR aprogram IN ('aprogram1') OR (aprogram IN ('aprogram2') AND PLAN_LDESCR IN ('plan123'))))
OR
(#deptname="deptB" AND (PROGRAM_LDESCR IN ('1234') OR aprogram IN ('a1234'))
)
Normally you would use the WHERE clause to filter out unnecessary rows of data and a CASE statement if you wanted to actually change the value in the SELECT statement (I rarely see CASE statements outside a SELECT clause, unless it is doing something like a complex sort).

Parameter index out of range (1 > number of parameters, which is 0) in SQL while passing ? argument in query

INSERT INTO JOB_AUDIT_HDR_LOG (APP_NM,BTCH_NUM,BTCH_RUN_STRT_TM,BTCH_RUN_STS_CD)
SELECT ? AS app_nm,
COALESCE(btch_num, 0) + 1 AS batch_num,
Now(),
'RUNNING'
FROM (SELECT 1) Dt1
LEFT OUTER JOIN(SELECT app_nm,
MAX(btch_num) AS btch_num
FROM gmicntrldb.JOB_AUDIT_HDR_LOG
WHERE app_nm = ?
GROUP BY app_nm)Dt2
ON 1 = 1;
While am running this query getting an error like Parameter index out of range (1 > number of parameters, which is 0).
You have 2 ?, which means you need to pass in a parameter array with entries for [0], and [1]. Looks like you're passing in only 1 (or maybe 0) parameters in your param array?

How to compare '>10' with 11 which is coming as parameter in mySql

This is the table i have.
And I need to select agains Condition column
select * from OfferCondition where Condition = '21'
for the above query, it should return 1st and 2nd row.
This requires a HAVING clause for each condition AND the conditions in order (so it stops at the first one... apart from that does as you request I think...
SET #iValue = 21;
SELECT substring_index(`Condition`,' ',1) AS Operator,
substring_index(substring_index(`Condition`,' ',2 ),' ', -1) AS Value
FROM OfferCondition
HAVING (Operator = '>' AND #iValue > Value)
OR (Operator = '>=' AND #iValue >= Value)
OR (Operator = '=' AND #iValue = Value)
LIMIT 1;
NOTE this also requires a space between the operator and operand - as pointed out elsewhere would be much better to include as separate columns

Codeigniter IFNULL in set() mysql activerecord

There is a column abc in a table xyz, whose datatype is int and the default value is null. We assume that a particular row exists in the table in which the value of the field abc is null.
I wish to change abc to 'its previous value + some other value' by running a query multiple times. The issue comes when updating the column first time since its value is null.
Adding null to anything returns null, so this doesn't work:
$this->db->set('abc', $value);
I tried using this instead:
$this->db->set('abc', "IFNULL(abc, 0) + $value");
But this produces:
UPDATExyzSETabc= 'IFNULL(abc, 0) + value'
But the required query is :
UPDATExyzSETabc= IFNULL(abc, 0) + value
(without the inverted commas for the value to be set)
Can this be achieved?
This doesn't work either:
$this->db->set('abc = IFNULL(abc, 0) + $value');
You may try to add the third parameter to FALSe (unescaped value)
$this->db->set('abc', 'IFNULL(abc, 0) + $value', FALSE);
or maybe
$this->db->set('abc', 'IFNULL(abc, 0) + '.$value.'', FALSE);

IF condition in mysql

I have a contact table I wish to query when a certain condition exists. I tried the query below but am getting a syntax error.
SELECT *
FROM contact_details
WHERE contactDeleted` =0
AND IF ( contactVisibility = "private"
, SELECT * FROM contact_details
WHERE contactUserId = 1
, IF( contactVisibility = "group"
, SELECT * FROM contact_details
WHERE contactGroup = 3
)
)
If I'm understanding your question correctly (which is difficult with the lack of info you've provided. Sample datasets and expected outcomes are typically helpful), then I don't believe you need IFs at all for what you want. The following will return contacts that are not deleted and who either have (visibility = "private" and userId = 1) OR (visibility = "group" and group = 3)
SELECT *
FROM contact_details
WHERE contactDeleted = 0
AND (
(contactVisibility = "public")
OR
(contactVisibility = "private" AND contactUserId = 1)
OR
(contactVisibility = "group" AND contactGroup = 3)
)
I am assuming you want to use the IF() function and not the statement which is for stored functions..
Refer to this link for more information on that.
Notice that you have put 2 select statements in there, where the custom return values are supposed to be. So you are returning a SELECT *... now notice that in your upper level sql statement you have an AND.. so you basically writing AND SELECT *.. which will give you the syntax error.
Try using .. AND x IN (SELECT *) .. to find if x is in the returned values.
Let me also list this link to make use of an existing and well written answer which may also applicable to your question.