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).
Related
*** SOLUTION IN BOTTOM****
I am trying to add some comment at last column of my query , basically if technical_document.disc_id contains "KN" then i want to add a comment to the last column of query 'OK'
but i cant get it working
SELECT
technical_document.project_no,
technical_document.doc_no,
technical_document.doc_class,
technical_document.disc_id,
tag_document.project_id AS "COMMENT"
CASE WHEN technical_document.disc_id = 'KN' THEN tag_document.project_id = "YES"
FROM technical_document left join tag_document on technical_document.doc_no = tag_document.proj_doc_doc_no
WHERE tag_document.proj_doc_doc_no IS NULL
AND technical_document.project_no like '%%'
AND technical_document.doc_class = ANY ('A','S','SE')
AND technical_document.Lci_Code = ANY ('A','A1','B')
Thanks for your help, here is how it was solved, sorry for confusing/misleading explanation on my part:
SELECT
technical_document.project_no,
technical_document.doc_no,
technical_document.doc_class,
technical_document.disc_id,
CASE
WHEN technical_document.disc_id LIKE 'KN' THEN 'OK'
WHEN technical_document.disc_id LIKE 'K6' THEN 'OK'
ELSE null
END
FROM technical_document left join tag_document on technical_document.doc_no = tag_document.proj_doc_doc_no
WHERE tag_document.proj_doc_doc_no IS NULL
AND technical_document.project_no like '%%'
AND technical_document.doc_class = ANY ('A','S','SE')
AND technical_document.Lci_Code = ANY ('A','A1','B')
I would write the query as:
SELECT d.project_no, d.doc_no, d.doc_class, d.disc_id,
d.project_id AS COMMENT,
(CASE WHEN td.disc_id = 'KN' THEN td.project_id = 'YES' END)
FROM technical_document d LEFT JOIN
tag_document td
ON d.doc_no = td.proj_doc_doc_no
WHERE d.proj_doc_doc_no IS NULL AND
d.project_no like '%%' AND -- not needed
d.doc_class IN ('A', 'S', 'SE') AND
d.Lci_Code IN ('A', 'A1', 'B');
First, you have a WHERE clause that says that there is no match. Hence, including columns in the SELECT from tag_document doesn't make sense. I suspect you intend:
SELECT d.project_no, d.doc_no, d.doc_class, d.disc_id,
d.project_id as COMMENT,
(CASE WHEN td.disc_id = 'KN' THEN td.project_id = 'YES' END)
FROM technical_document d LEFT JOIN
tag_document td
ON d.doc_no = td.proj_doc_doc_no AND td.disc_id = 'KN'
WHERE d.project_no like '%%' AND -- not needed
d.doc_class IN ('A', 'S', 'SE') AND
d.Lci_Code IN ('A', 'A1', 'B');
Note the condition on td in the WHERE clause has been removed.
In addition:
Table aliases make the query easier to write and to read.
= ANY is allowed, but the colloquial operator is IN.
Various small syntax errors are fixed -- missing commas, missing END.
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.
I am trying to display a field value based on the value of field and then find a external table record.
can I do it?
SELECT
CASE
WHEN (dsp_notes IS NOT NULL) THEN '*'
WHEN (dsp_notes IS NULL) THEN ''
ELSE ''
END,
CASE
WHEN (dsp_priority = '1') THEN [SELECT uvi_value FROM PUB.universalinfo WHERE uvi_key = 'DSP01SHORT']
Is this possible?
Yes. This is called a scalar subquery and it needs to return one column and one row:
(CASE WHEN dsp_priority = '1'
THEN (SELECT ui.uvi_value FROM PUB.universalinfo ui WHERE ui.uvi_key = 'DSP01SHORT')
END) as NewCol
I strongly encourage you to use table aliases on your column references.
I want to write a select statement that should filter data based on wildcard characters. I have written something like this but it doesn't serve my purpose:
Select r.CompanyID,r.Description,c.BusinessUnitID,c.BusinessSourceID as BusinessSrcID,
c.Description as BusinessDesc from RCompanyTable r
join CBusinessUnitTable c on r.CompanyID=c.CompanyID
WHERE r.CompanyID like CASE WHEN COALESCE('Regexp(*)', '') = '' THEN r.CompanyID ELSE 'Company2' END
But in this it always executes the else part.
What i am looking for is it should give me all data when i pass * to the condition.
Since in my RCompanyTable i have two records Company1 and Company2, I want that if i pass * in that query then it should return me both company1 and company2 data but if i pass regexp(any1) it should provide me Comapany1 Data and if both conditions are not true then it should go to else part displaying Company2 data
Looking forward to your answer.
Thanks in advance
I don't know exactly what you want with * and regexp(any1), but assuming that they are constant strings, then this query should work:
SET #parameter = '';
Select r.CompanyID
, r.Description
, c.BusinessUnitID
, c.BusinessSourceID AS BusinessSrcID
, c.Description AS BusinessDesc
FROM RCompanyTable r
JOIN CBusinessUnitTable c ON r.CompanyID = c.CompanyID
WHERE (#parameter LIKE '%*%' AND r.CompanyID IN ('Company1', 'Company2'))
OR (#parameter LIKE 'regexp(any1)' AND r.CompanyID = 'Company1')
OR (#parameter NOT IN ('%*%', 'regexp(any1)') AND r.CompanyID = 'Company2')
The #parameter is what you are going to pass in the query.
WHERE r.CompanyID = CASE WHEN r.CompanyId LIKE '%*%' THEN r.CompanyID ELSE 'Company2' END
This where clause returns all records where companyID has a * in it, or the companyID is Company2. Is this what you are after?
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.