ORA-01795: maximum number of expressions in a list is 1000 error in perl script - oracle

I'm trying to run a query with NOT IN clause like:
SELECT * FROM table WHERE column NOT IN (?,?,...) (>1000 items) and I'm getting ORA-01795: maximum number of expressions in a list is 1000 error.
In my script I'm doing something like:
my $lparam = join ', ' => ('?') x #ids;
$lquery = "SELECT * FROM table WHERE column NOT IN ($lparam)";
$lcsr = $zdb->prepare($lquery);
$lcsr->execute( #ids );
I want to split the NOT IN clause to something like where (A not in (a,b,c) AND A not in (d,e,f)) ... How can we achieve this?

Here you go, adding triples and counting them.
my $count = 0;
$lquery = "SELECT * FROM table WHERE (A ";
while (#ids -$count > 3) {
$lquery .= "NOT in (?, ?, ?) AND A ";
$count += 3;
}
my $lparam = join ', ' => ('?') x (#ids - $count);
$lquery .= "NOT IN ($lparam))";

You can go with the IN list using a combination of the column as follows:
SELECT * FROM table WHERE (column,1) NOT IN ((?,1),(?,1),...) (>1000 items)
Here, 1 is used as the second column. And you can give more than 1000 values in the IN clause list. It is a workaround of skipping the limit.

Related

JdbcPagingItemReader Spring batch skipping last element

I have a table with this structure:
CNMA_CO_PLATFORM_MESSAGE|AUDI_TI_CREATION|FIELD4|OTHER FIELDS
test-jj#2774#20210422112434957#00026129|22/04/21 11:24:34,957000000|11|..
test-jj2#2774#20210422112434957#00026129|22/04/21 11:24:34,957000000|12|..
test-jj3#2774#20210422112434957#00026129|22/04/21 11:24:34,957000000|13|..
This combination is the PRIMARY_KEY of the table:
CNMA_CO_PLATFORM_MESSAGE|AUDI_TI_CREATION
Well, I have an JdbcPagingItemReader defined like this (Pagesize is 1):
#StepScope
#Bean
public JdbcPagingItemReader<PendingNotificationDTO> pendingNotificationReader(
#Value("#{stepExecution}") StepExecution stepExecution){
final JdbcPagingItemReader<PendingNotificationDTO> reader = new JdbcPagingItemReader<>();
reader.setDataSource(daoDataSource);
reader.setName("pendingNotificationReader");
//Creamos la Query
final OraclePagingQueryProvider oraclePagingQueryProvider = new OraclePagingQueryProvider();
oraclePagingQueryProvider.setSelectClause("SELECT " +
" cegct.AUDI_TI_CREATION, "+
" CNMA_CO_PLATFORM_MESSAGE, " +
" OTHERFIELDS... ");
oraclePagingQueryProvider.setFromClause("FROM TABLE1 cegct " +
" JOIN TABLE1 notip ON cegct.field1 = notip.field1 " +
" AND notip.field2 = :frSur ");
oraclePagingQueryProvider.setWhereClause("WHERE "
+ " cegct.field3 = 0 "
+ " AND cegct.field4 in (:notifStatusList) ");
//Indicamos conjunto de campos no repetibles para poder paginar
Map<String, Order> sortKeys = new HashMap<>();
sortKeys.put("CNMA_CO_PLATFORM_MESSAGE", Order.DESCENDING);
sortKeys.put("AUDI_TI_CREATION", Order.DESCENDING);
oraclePagingQueryProvider.setSortKeys(sortKeys );
reader.setQueryProvider(oraclePagingQueryProvider);
String frSur = stepExecution.getJobExecution().getExecutionContext().getString(Constants.FM_ROLE_SUR_ZK);
String notifStatus = stepExecution.getJobExecution().getExecutionContext().getString(Constants.STATUS_REPORTS);
Map<String, Object> parameters = new HashMap<>();
parameters.put("frSur", frSur);
parameters.put("notifStatusList", Arrays.asList(StringUtils.split(notifStatus, ",")));
reader.setParameterValues(parameters );
Integer initLoaded = stepExecution.getJobExecution().getExecutionContext().getInt(Constants.RECOVER_PENDING_NOT_COMMIT);
reader.setPageSize(initLoaded);
reader.setRowMapper(new BeanPropertyRowMapper<PendingNotificationDTO>(PendingNotificationDTO.class));
return reader;
}
(I hide some irrelevant fields and table names)
Well, I run a test and my 3 records are valid to the select, these are selected one to one by the page size. Anyway, the first chunk-reader generated select my "test-jj3#..." record, my second chunk-reader select "test-jj2#.." and my third chunk-reader doesn't select doesn't recover any record (It should recover last 'test-jj#...' element.
These are the generated sqls (I hide some sensible no relevant fields)
First chunk, Select 1 register
SELECT * FROM (
SELECT
cegct.AUDI_TI_CREATION
CNMA_CO_PLATFORM_MESSAGE, [otherfields]
FROM [FROM]
WHERE [where]
ORDER BY CNMA_CO_PLATFORM_MESSAGE DESC, AUDI_TI_CREATION DESC
) WHERE ROWNUM <= 1;
Second chunk, Select 1 register (Here, the rownum filter by the sortkeys)
SELECT * FROM (
SELECT
cegct.AUDI_TI_CREATION
CNMA_CO_PLATFORM_MESSAGE, [otherfields]
FROM [FROM]
WHERE [where]
ORDER BY CNMA_CO_PLATFORM_MESSAGE DESC, AUDI_TI_CREATION DESC
) WHERE
ROWNUM <= 1 AND (
(CNMA_CO_PLATFORM_MESSAGE < 'test-jj3#2774#20210422112434957#00026129')
OR
(CNMA_CO_PLATFORM_MESSAGE = 'test-jj3#2774#20210422112434957#00026129' AND AUDI_TI_CREATION < TO_DATE('2021-04-22 11:24:34', 'YYYY-MM-DD HH24:MI:SS'))
);
Third chunk, select 0 registers
SELECT * FROM (
SELECT
cegct.AUDI_TI_CREATION
CNMA_CO_PLATFORM_MESSAGE, [otherfields]
FROM [FROM]
WHERE [where]
ORDER BY CNMA_CO_PLATFORM_MESSAGE DESC, AUDI_TI_CREATION DESC
) WHERE
ROWNUM <= 1 AND (
(CNMA_CO_PLATFORM_MESSAGE < 'test-jj2#2774#20210422112434957#00026129')
OR
(CNMA_CO_PLATFORM_MESSAGE = 'test-jj2#2774#20210422112434957#00026129' AND AUDI_TI_CREATION < TO_DATE('2021-04-22 11:24:34', 'YYYY-MM-DD HH24:MI:SS'))
);
Sorry for my english, I hope you can understand my problem.
Logs for the Prepared SQL Statement
Executing prepared SQL statement [SELECT * FROM (
SELECT
cegct.AUDI_TI_CREATION,
CNMA_CO_PLATFORM_MESSAGE,
OTHERFIELDS...
FROM TABLE1 cegct
JOIN TABLE2 notip ON cegct.field1 = notip.field1
AND notip.field2 = ?
WHERE cegct.field3 = 0
AND cegct.field4 in (?, ?, ?)
ORDER BY CNMA_CO_PLATFORM_MESSAGE DESC, AUDI_TI_CREATION DESC) WHERE ROWNUM <= 1]
20221116 12:52:43.560 TRACE org.springframework.jdbc.core.StatementCreatorUtils [[ # ]] - Setting SQL statement parameter value: column index 1, parameter value [1], value class [java.lang.String], SQL type unknown
20221116 12:52:43.560 TRACE org.springframework.jdbc.core.StatementCreatorUtils [[ # ]] - Setting SQL statement parameter value: column index 2, parameter value [11], value class [java.lang.String], SQL type unknown
20221116 12:52:43.560 TRACE org.springframework.jdbc.core.StatementCreatorUtils [[ # ]] - Setting SQL statement parameter value: column index 3, parameter value [12], value class [java.lang.String], SQL type unknown
20221116 12:52:43.560 TRACE org.springframework.jdbc.core.StatementCreatorUtils [[ # ]] - Setting SQL statement parameter value: column index 4, parameter value [13], value class [java.lang.String], SQL type unknown
A bind variable is a single value; therefore when you use:
AND cegct.field4 in (:notifStatusList)
Then :notifStatusList is a single string and is NOT a list of values and you effectively doing the same as:
AND cegct.field4 = :notifStatusList
If the bind variable :notifStatusList is a single value then it will work; however, when you try to pass in multiple values then it will not match those multiple values but will try to match field4 to the entire delimited list (which fails and will filter out all the rows).
If you want to pass a delimited string then use:
AND ',' || :notifStatusList || ',' LIKE '%,' || cegct.field4 || ',%'
Alternatively, pass the values as an array (rather than a delimited string) into an Oracle collection and then test to see if it is in that collection.

Codeigniter Active record And Or combinations in where clause with multiple & nested groups

I have a complex SQL query and I want to implement it through Active Records. This query has several AND / OR clauses grouped together with another criteria. I have gone through various articles where they said that we can use group_start() and group_end() but I am wondering if a group can be started inside another group too? The resulting serial numbers needs to be excluded from the result set to be produced by the outer query. Actually I tried using Join here, but it didn't work. Any working idea regarding joins here will be appreciable too.
As you can see in the query below, I have used double round brackets to represent multiple groups inside a group.
The resulting serial numbers needs to be excluded from the results of outer query too. Please tell me what will be its Codeigniter Active Record equivalent code.
select * from table2 WHERE NOT table2.serial IN (select columnname from table where ((col < val and val < col) or (col < val and val < col) or(val=col and val=col)) AND incol=intval AND intcol=intval)
Here, col is the column name, val is a value of DATE type, intval is
an Integer value
Try this syntax
$this->db->select("*")->from("table");
$this->db->group_start();
$this->db->group_start();
$this->db->where("val <",'col');
$this->db->where("val <",'col');
$this->db->group_end();
$this->db->or_group_start();
$this->db->or_where("val <",'col');
$this->db->where("val <",'col');
$this->db->group_end();
$this->db->or_group_start();
$this->db->or_where("val ",'col');
$this->db->where("val ",'col');
$this->db->group_end();
$this->db->group_end();
$this->db->where("incol ",'intval');
$this->db->where("incol ",'intval');
$this->db->get();
$last_query = $this->db->last_query();
$this->db->select('*')->from('table2');
$this->db->where_not_in('serial',$last_query);
$this->db->get();
echo $this->db->last_query();
The query string produced by the above is
SELECT * FROM `table2` WHERE
`serial` NOT IN(
SELECT columnname FROM `table` WHERE
(
(`val` < 'col' AND `val` < 'col') OR
(`val` < 'col' AND `val` < 'col') OR
(`val` = 'col' AND `val` = 'col')
) AND `incol` = 'intval' AND `incol` = 'intval'
);

DAX pick a value from tied resultset

i need help with the following dax statement.
Situation:
I have 2 tables. One table contains sell data with articleIDs, dateIDs and sell prices, another table contains stock movements data with articleIDs, dateIDs and purchase prices. According to the dateID i want to write the purchase prices into the first table using a calculated column because i need the prices for every row.
Example:
Table1 t1
t1.articleID = 123; t1.dateID = 20160905; t1.sellPrice = 62,55; t1.purchasePrice = My DAX Statement
Table2 t2
t2.articleID = 123; t2.dateID = 20160905; t2.purchasePrice = 37,07
t2.articleID = 123; t2.dateID = 20160905; t2.purchasePrice = 37,07
t2.articleID = 123; t2.dateID = 20160906; t2.purchasePrice = 37,07
t2.articleID = 456; t2.dateID = 20160905; t2.purchasePrice = 12,15
My DAX Statement:
= CALCULATE (
VALUES (t2[purchasePrice]);
TOPN (
1;
FILTER(FILTER(t2; t2[articleID] = t1[articleID]); t2[dateID] <= t1[dateID]); t2[dateID]; DESC
)
)
With my DAX Statement i get the following error:
A table of multiple values was supplied where a single value was expected.
It is normal that i have more than one row matching in the table 2.
Actually I just want the price of any of them on the corresponding dateID, even if they are tied. So i used the TOPN function with the value 1 and sorted by date but the error still remains. Is there a way to fix my DAX Statement to achieve this?
Create a calculated column in T1 and use this expression:
purchasePrice =
CALCULATE (
MAX ( T2[purchasePrice] ),
FILTER ( T2, T1[ArticleID] = T2[articleID] && T1[DateID] = T2[dateID] )
)
Note I use comma to separate passed arguments to the functions but I see in your expression you used semicolon. Change it to match your system list separator.
It is not tested but should work. Let me know if it works for you.

SQL query multiple joins not working

I am using oracle database and trying to run the following query but it gives the error:
"ERROR at line 17: ORA-00904: "FRH"."NS": invalid identifier"
What is the problem with it?
Following is the query:
SELECT *
FROM
(SELECT *
FROM ROOMS R
WHERE R.Prix<'50') FRM
JOIN
(SELECT *
FROM
(SELECT *
FROM HOTELS H
WHERE H.CatH=2) FH
JOIN
(SELECT *
FROM RESORTS R
WHERE TypeS='montagne') FR
ON FH.NS=FR.NS) FRH
ON (FRH.NS=FRM.NS AND FRH.NH=FRM.NH);
Thanks in advance
You have way too many nested selects here. Your query can be simplified to:
SELECT *
FROM rooms rm
JOIN hotels ht ON ht.ns = rm.ns AND ht.nh = rm.nh
JOIN resorts rs ON rs.ns = ht.ns
WHERE rm.prix < 50
AND ht.cath = 2
AND ss.types = 'montagne';
I am not entirely sure which tables need to be joined using just the ns column and which need both the ns and nh column because you have obfuscated your query so much and did not show us the table definitions.
Alternatively you can move the restrictions on the joined tables into the join condition. This isn't necessary for the inner joins you are using, but could be needed if you ever want to change that to an outer join:
SELECT *
FROM rooms rm
JOIN hotels ht ON ht.ns = rm.ns AND ht.nh = rm.nh AND ht.cath = 2
JOIN resorts rs ON rs.ns = ht.ns AND rs.types = 'montagne'
WHERE rm.prix < 50;
You should also not compare numbers and strings. Assuming rooms.prix is a number column, the condition R.Prix<'50' is wrong. You need to compare the number to a number r.prix < 50

How do I return last n records in the order of entry

From Laravel 4 and Eloquent ORM - How to select the last 5 rows of a table, but my question is a little different.
How do I return last N records ordered in the way they were created (ASC).
So for example the following records are inserted in order:
first
second
third
fourth
fifth
I want a query to return last 2 records
fourth
fifth
Laravel Offset
DB::table('users')->skip(<NUMBER Calulation>)->take(5)->get();
You can calculate N by getting the count of the current query and skipping $query->count() - 5 to get the last 5 records or whatever you wanted.
Ex
$query = User::all();
$count = ($query->count()) - 5;
$query = $query->skip($count)->get();
In pure SQL this is done by using a subquery. Something like this:
SELECT * FROM (
SELECT * FROM foo
ORDER BY created_at DES
LIMIT 2
) as sub
ORDER BY created_at ASC
So the limiting happens in the subquery and then in the main query the order by is reversed. Laravel doesn't really have native support for subqueries. However you can still do it:
$sub = DB::table('foo')->latest()->take(2);
$result = DB::table(DB::raw('(' . $sub->toSql() . ') as sub'))
->oldest()
->get();
And if you use Eloquent:
$sub = Foo::latest()->take(2);
$result = Foo::from(DB::raw('(' . $sub->toSql() . ') as sub'))
->oldest()
->get();
Note the latest and oldest just add an orderBy('created_at) with desc and asc respectively.

Resources