Codeigniter IF inside $this->db->select - codeigniter

i have codeigniter code
$this->db->select("items.name as name, items.category as category, items.supplier_id as supplier_id, items.item_number as item_number,
items.product_id as product_id, items.description as description,
items.size as size, items.tax_included as tax_included, items.cost_price as cost_price,
if(price_tiers.name='".$hasilsplit1."',items_tier_prices.unit_price,items.unit_price) as unit_price, items.promo_price as promo_price,
items.start_date as start_date, items.end_date as end_date, items.reorder_level as reorder_level, items.item_id as item_id, items.allow_alt_description as allow_alt_description, items.is_serialized as is_serialized, items.image_id as image_id, items.override_default_tax as override_default_tax, items.is_service as is_service, items.deleted as deleted");
$this->db->from('items');
$this->db->join('items_tier_prices','items_tier_prices.item_id=items.item_id','left');
$this->db->join("price_tiers","price_tiers.id=items_tier_prices.tier_id and price_tiers.name='".$hasilsplit1."'","left");
$this->db->where('items.item_id', $hasilsplit0);
$this->db->where('items.deleted', 0);
it generates error on part:
if(price_tiers.name='".$hasilsplit1."',items_tier_prices.unit_price,items.unit_price) as unit_price
the error is:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'as unit_price, items.promo_price as promo_price, items.start_date as sta' at line 1
how to write IF syntax correctly inside $this->db->select?
when i var_dump, it shows
SELECT items.name as name, items.category as category, items.supplier_id as supplier_id, items.item_number as item_number, items.product_id as product_id, items.description as description, items.size as size, items.tax_included as tax_included, items.cost_price as cost_price, if(price_tiers.name='Jendela Swing Double J106', items_tier_prices.unit_price, items.unit_price) as unit_price, items.promo_price as promo_price, items.start_date as start_date, items.end_date as end_date, items.reorder_level as reorder_level, items.item_id as item_id, items.allow_alt_description as allow_alt_description, items.is_serialized as is_serialized, items.image_id as image_id, items.override_default_tax as override_default_tax, items.is_service as is_service, items.deleted as deleted FROM (items) LEFT JOIN items_tier_prices ON items_tier_prices.item_id=items.item_id LEFT JOIN price_tiers ON price_tiers.id=items_tier_prices.tier_id and price_tiers.name='Jendela Swing Double J106' WHERE items.item_id = '1' AND items.deleted = 0
it seems if blocks getting character `
Thanks

I think you need to check the manual, and to try to disable escaping when compiling SELECT:
$this->db->select() accepts an optional second parameter. If you set it to FALSE, CodeIgniter will not try to protect your field or table names. This is useful if you need a compound select statement where automatic escaping of fields may break them.
And the second recommendation would be to escape SQL query, when you are using raw data, for example:
$this->db->escape($someString); // instead of using $someString when concatenating string for query.

Related

ORA-01722: invalid number while passing value from inner select query to the top select query

FOR the ISBN['9780495809135'] if CATEGORY_EXISTS column return as 1234,3454 then query is throwing below error.if it returns single row then its not throwing error.
I want to write in the topmost query say if CATEGORY_EXISTS ='Category Not Found' then FILE_NAME column then should display as 'files not found' otherwise pass the CATEGORY_EXISTS values with comma separated to top most most query.
Please note that this is just pseduo query,in the actual query lot of other tables and joins are there,
ORA-01722: invalid number
01722. 00000 - "invalid number"
*Cause: The specified number was invalid.
*Action: Specify a valid number.
SELECT ISBN ,
(SELECT LISTAGG(ANP.FILE_NAME, ',') WITHIN GROUP (
ORDER BY ANP.FILE_NAME)
FROM TABLE1 T
WHERE T.NODE_ID IN( CATEGORY_EXISTS)
)FILE_NAME
FROM
(SELECT ISBN,
(SELECT (
CASE
WHEN COUNT(DISTINCT AN.ID) > 0
THEN LISTAGG(AN.ID, ',') WITHIN GROUP (
ORDER BY AN.ID)
ELSE 'Category Not Found'
END )
FROM TABLE1 aca
JOIN TABLE2 AN
ON ACA.CHILD_NODE_ID=AN.ID
WHERE PARENT_NODE_ID=GT_CHILD_NODE_ID
) CATEGORY_EXISTS
FROM
(SELECT ISBN,
(SELECT ID FROM TEMP_CHILD_ASSOC ac WHERE CHILD_NODE_NAME=GT.ISBN
) GT_CHILD_NODE_ID
FROM MAIN_TABLE GT
WHERE ISBN='9780495809135'
)
);
The listagg() function generates a string of comma-separated values (if there is more than one ID). The case expression gives you either that generated string, of the fixed text literal (if there are no IDs). You are then trying to compare that string to a number; effectively one of these:
WHERE T.NODE_ID IN ('4321')
WHERE T.NODE_ID IN ('1234,3454')
WHERE T.NODE_ID IN ('Category Not Found')
You are implicitly converting the string to a number to compare it with NODE_ID. The first one will work as the implicit conversion is valid. The second will give you ORA-01722 (unless you have exactly two values, and your NLS decimal separator is a comma; but still won't give a match), and the third will also give that error - because those strings cannot be converted to numbers.
It's possible you are expecting the second one to be magically treated as two numbers inside the IN() clause, but that isn't how it works; it's getting a single string literal, not an actual list of numbers it can understand.
The IN condition does accept a list of multiple comma-separated expressions, but you are passing in a single string. The fact that string happens to consist of comma-separated values is irrelevant: it is itself still just a single expression. And that cannot be converted implicitly to a number.
If you have, or can create, a schema-level table type like:
create type my_number_tab as table of number
/
then you could use the collect() function to convert the IDs into a collection instead of a string, and then use member of to find matches; something like (with a bit of interpretation of your pseudocode):
SELECT ISBN ,
(SELECT LISTAGG(ANP.FILE_NAME, ',') WITHIN GROUP (
ORDER BY ANP.FILE_NAME)
FROM TABLE3 ANP
WHERE ANP.NODE_ID MEMBER OF CATEGORIES -- use collection
)FILE_NAME
FROM
(SELECT ISBN,
(SELECT CAST(COLLECT(AN.ID) AS my_number_tab) -- create collection not string
FROM TABLE1 aca
JOIN TABLE2 AN
ON ACA.CHILD_NODE_ID=AN.ID
WHERE PARENT_NODE_ID=GT_CHILD_NODE_ID
) CATEGORIES
FROM
(SELECT ISBN,
(SELECT ID FROM TEMP_CHILD_ASSOC ac WHERE CHILD_NODE_NAME=GT.ISBN
) GT_CHILD_NODE_ID
FROM MAIN_TABLE GT
WHERE ISBN='9780495809135'
)
);
It looks like you could also join to anp inside the inner query instead, so in that you generate the string list of file names rather than (or as well as) the string list of IDs. It's hard to tell from the pseudocode though; but perhaps something like:
SELECT ISBN,
(SELECT (
CASE
WHEN COUNT(DISTINCT AN.ID) > 0
THEN LISTAGG(ANP.FILE_NAME, ',') WITHIN GROUP (
ORDER BY ANP.FILE_NAME)
ELSE 'Category Not Found'
END )
FROM TABLE1 aca
JOIN TABLE2 AN
ON ACA.CHILD_NODE_ID=AN.ID
JOIN TABLE3 ANP
ON ANP.NODE_ID=AN.ID
WHERE ACA.PARENT_NODE_ID=GT_CHILD_NODE_ID
) FILE_NAME
FROM
(SELECT ISBN,
(SELECT ID FROM TEMP_CHILD_ASSOC ac WHERE CHILD_NODE_NAME=GT.ISBN
) GT_CHILD_NODE_ID
FROM MAIN_TABLE GT
WHERE ISBN='9780495809135'
);
You could probably also do the same thing with left outer joins (though perhaps they don't all need to be), although your comment suggests you have a reason for using subqueries instead:
SELECT GT.ISBN,
CASE WHEN COUNT(AN.ID) = 0 THEN 'files not found'
ELSE LISTAGG(ANP.FILE_NAME, ',') WITHIN GROUP (ORDER BY ANP.FILE_NAME)
END AS file_name
FROM MAIN_TABLE GT
LEFT JOIN TEMP_CHILD_ASSOC ac ON CHILD_NODE_NAME=GT.ISBN
LEFT JOIN table1 aca ON aca.parent_node_id = ac.id
LEFT JOIN table2 an on an.id = ACA.CHILD_NODE_ID
LEFT JOIN table3 anp on anp.node_id = an.id
WHERE GT.ISBN = '9780495809135'
GROUP BY GT.ISBN;
or something like that; again hard to tell from the pseudocode...

Informatica Powercenter Add Select LISTAGG query

I have learning informatica powercenter. I was able to do an INNER JOIN between two VIEWs. I added the INNER JOIN in the User Defined Join but still have to make correct changes in the Sql Query when click on Validate. Do I just need to only add to User Defined Join when I am joining VIEWS?
Here is my problem. I got another VIEWs which is one to many, so this will be my 3rd VIEW to add to the query. I got this running on TOAD. How do I add this to Infromatica? Do I just avoid the Sql Query section and add the entire query into User Defined Query? Do LISTAGG works in Informatica?
If not in the Query for LISTAGG (one-many relationship), is it better or is there a way to do this in the transformation like expression transformation?
Thanks.
This query is a SELECT, LISTAGG, CASE
SELECT PERSON_ID,
FIRST_NAME,
MIDDLE_NAME,
LAST_NAME,
LISTAGG(val,',') WITHIN GROUP (ORDER BY Table2.SKILL_SHORT_DESC )
FROM (SELECT DISTINCT Table1.PERSON_ID,
Table1.FIRST_NAME,
Table1.MIDDLE_NAME,
Table1.LAST_NAME,
(case
when Table2.SKILL_SHORT_DESC = '1' then '1:1'
when Table2.SKILL_SHORT_DESC = '2' then '2:2'
when Table2.SKILL_SHORT_DESC = '3' then '3:3'
when Table2.SKILL_SHORT_DESC = '4' then '4:4'
when Table2.SKILL_SHORT_DESC = '5' then '5:5'
when Table2.SKILL_SHORT_DESC = '6' then '6:6'
when Table2.SKILL_SHORT_DESC = '7' then '7:7'
when Table2.SKILL_SHORT_DESC = '8' then '8:8'
when Table2.SKILL_SHORT_DESC = '9' then '9:9'
else ''
end) as val
FROM Table1
LEFT JOIN Table2
ON Table2.PERSON_ID = Table1.PERSON_ID
)
GROUP BY PERSON_ID,FIRST_NAME,MIDDLE_NAME, LAST_NAME
Yes, LISTAGG should work. Assuming you are using oracle, it should work 10.x and higher version. Frankly, Informatica doesn't care what you write as SQL but its the database where SQL is being issued matters. You can write 'I am batman' and infa will return, 'Invalid syntax'.
Koushik
Please follow below steps,
Get any dummy source from the table
In source qualifier, remove all the ports and create the ports you required
In properties --> Sql query, add the query you have created. No need to provide any user defined joins
Below are the screen shots for better understanding.

Hive LATERAL VIEW and WHERE Clause using Sub query

I'm looking for a way to optimize my query.
We have a table with events called lea, with a column app_properties, which are tags, stored as a comma separated string.
I would like to select all the events that match the result of a query that select the desired tags.
My first try:
SELECT uuid, app_properties, tag
FROM events
LATERAL VIEW explode(split(app_properties, '(, |,)')) tag_table AS tag
WHERE tag IN (SELECT source_value FROM mapping WHERE indicator = 'Bandwidth Usage')
But Hive will not allow this...
FAILED: SemanticException [Error 10249]: Line 4:6 Unsupported SubQuery Expression 'tag': Correlating expression cannot contain unqualified column references.
Gave it another try by replacing WHERE tag IN by WHERE tag_table.tag IN but not luck...
FAILED: SemanticException Line 4:6 Invalid table alias tag_table' in definition of SubQuery sq_1 [tag_table.tag IN (SELECT source_value FROM mapping WHERE indicator = 'Bandwidth Usage')] used as sq_1 at Line 4:20.
In the end... The query below gives the desired result, but I've a feeling that this is not the most optimized way of solving this use case. Has anyone ran into the same use case where you need the select from a LATERAL VIEW using a Sub query?
SELECT to_date(substring(events.time, 0, 10)) as date, t2.code, t2.indicator, count(1) as total
FROM events
LEFT JOIN (
SELECT distinct t.uuid, im.code, im.indicator
FROM mapping im
RIGHT JOIN (
SELECT tag, uuid
FROM events
LATERAL VIEW explode(split(app_properties, '(, |,)')) tag_table AS tag
) t
ON im.source_value = t.tag AND im.indicator = 'Bandwidth Usage'
WHERE im.source_value IS NOT NULL
) t2 ON (events.uuid = t2.uuid)
WHERE t2.code IS NOT NULL
GROUP BY to_date(substring(events.time, 0, 10)), t2.code, t2.indicator;
The Hive subquery in the WHERE clause can be used with IN, NOT IN, EXIST, or NOT
EXIST as follows. If the alias (see the following example for the employee table) is not specified before columns (name) in the WHERE condition, Hive will report the error Correlating expression cannot contain unqualified column references. This is a limitation of the Hive subquery.
From Apache Hive Essentials.
I guess this problem is also caused by subquery.
events should have an alias

ORA-00904: invalid column name but I am using the correct column name

Can someone see where I am going wrong in the below query? I am getting the error message that the GROUP BY column doesn't exist, but it clearly does as I see that column name in the output when I don't use the GROUP BY.
SELECT
(SELECT customer_address.post_code FROM customer_address WHERE customer_address.address_type = 0 AND customer_address.customer_no = orders.customer_no) postcode, SUM(orders.order_no) orders
FROM
orders, customer_address
WHERE
orders.delivery_date = '27-MAY-15'
GROUP BY
postcode;
The answer is: You cannot use an alias name in GROUP BY.
So:
GROUP BY (SELECT customer_address.post_code ...);
Or:
select postcode, sum(order_no)
from
(
SELECT
(SELECT customer_address.post_code FROM customer_address WHERE customer_address.address_type = 0 AND customer_address.customer_no = orders.customer_no) postcode,
orders.order_no
FROM orders, customer_address
WHERE orders.delivery_date = '27-MAY-15'
)
GROUP BY postcode;
EDIT:
However, your query seems wrong. Why do you cross-join orders and customer_address? By mistake I guess. Use explicit joins (INNER JOIN customer_address ON ...), when using joins to avoid such errors. But here I guess you'd just have to remove , customer_address.
Then why do you add order numbers? That doesn't seem to make sense.

ORA-000932 When joining an xmltype to a varchar field

a little backstory, i have a comma delimited column in a database, that i have tried to convert into a many to many junction table, so instead of having
ID REPORT
1 5,6,7
i would see
ID REPORT
1 5
1 6
1 7
the query below does just that, and seems to work correctly,
with t as (select id,hqcat from report)
SELECT id, EXTRACT(column_value,'/e/text()') hqcat from t x,
TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE('<ROW><e>'||REPLACE(hqcat,',','</e><e>')||'</e></ROW>'),'//e')))
however when i try to join it to my lookup table by hqcat, i get a ORA-00932 error about inconstant data types, please help me, how do i change my original query to make it work with other tables and joins?
here is the join causing the error:
select *
from BIN03 a11
join ( with t as (select id,hqcat from report)
SELECT id, EXTRACT(column_value,'/e/text()') hqcat from t x,
TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE('<ROW><e>'||REPLACE(hqcat,',','</e><e>')||'</e></ROW>'),'//e')))) a12
on (a11.CODE = a12.HQCAT);
Thank you!
i've also tried to create my new "many to many" view as so:
WITH TAB AS
( (select id ID, hqcat STR from report))
SELECT ID as ID,
REGEXP_SUBSTR (STR, '[^,]+', 1, LEVEL) HQCAT FROM TAB
CONNECT BY LEVEL <= (regexp_count(str,',') + 1);
but this just reduces query speeds by 1000's.....
The (deprecated) extract function returns an XMLType, not a varchar2. You can cast it to the type you want, either in the inline view:
cast(EXTRACT(column_value,'/e/text()') as varchar2(3))
or when comparing the value:
a11.CODE = cast(a12.HQCAT as varchar2(3))
I've guessed the variable size you need, obviously, you might need it to be different. You could also use the XMLType getStringVal() function as shown below.
It seems little odd to mix an old-style cross join with a comma in the inline view's from clause, with ANSI joins in the rest, and you can get odd (or hard to debug, anyway) results doing that. You could also use another CTE for clarity:
with t as (select id, hqcat from report),
a12 as (
select id, extract(column_value,'/e/text()').getstringval() hqcat
from t
cross join table(xmlsequence(extract(xmltype('<ROW><e>'||
replace(hqcat,',','</e><e>')||'</e></ROW>'),'//e')))
)
select *
from a12
join bin03 a11 on a11.code = a12.hqcat;

Resources