Does cardinality in database return numeric values? - oracle

I am re-engineering code written in the SQL, and I got a use of cardinality in an order by clause. So on which basis it is going to order the records?
e.g.
ORDER BY
cardinality(emp_ids),
earliest_due_date
where emp_ids are prepared like this
CAST(
collect(employee.emp_id)
AS
NumberList
) AS emp_ids

It is documented that the return is numeric:
CARDINALITY returns the number of elements in a nested table. The
return type is NUMBER. If the nested table is empty, or is a null
collection, then CARDINALITY returns NULL.
So, your order by will return the emp_ids table with the least number of rows in it first (empty ones as it will return null will come last).

Related

find a best way to traverse oracle table

I have an oracle table. Table's DDL is (not have the primary key)
create table CLIENT_ACCOUNT
(
CLIENT_ID VARCHAR2(18) default ' ' not null,
ACCOUNT_ID VARCHAR2(18) default ' ' not null,
......
)
create unique index UK_ACCOUNT
on CLIENT_ACCOUNT (CLIENT_ID, ACCOUNT_ID)
Then, the data's scale is very huge, maybe 100M records. I want to traverse this whole table's data with batch.
Now, I use the table's index to batch traverse. But I have some oracle grammar problems.
# I want to use this SQL, but grammar error.
# try to use b-tree's index to locate start position, but not work
select * from CLIENT_ACCOUNT
WHERE (CLIENT_ID, ACCOUNT_ID) > (1,2)
AND ROWNUM < 1000
ORDER BY CLIENT_ID, ACCOUNT_ID
Has the fastest way to batch touch table data?
Wild guess:
select * from CLIENT_ACCOUNT
WHERE CLIENT_ID > '1'
and ACCOUNT_ID > '2'
AND ROWNUM < 1000;
It would at least compile, although whether it correctly implements your business logic is a different matter. Note that I have cast your filter criteria to strings. This is because your columns have a string datatype and you are defaulting them to spaces, so there's a high probability those columns contain non-numeric values.
If this doesn't solve your problem, please edit your question with more details; sample input data and expected output is always helpful in these situations.
Your data model seems odd.
Your columns are defined as varchar2. So why is your criteria numeric?
Also, why do you default the key columns to space? It would be better to leave unpopulated values as null. (To be clear, NULL is not a good thing in an indexed column, it's just better than a space.)

Why oracle uses index skip scan for this query?

The SQL queries only one table, the table has 100 millions rows.
The SQL has three columns in the where clause, col_date, col_char1 and col_char2. col_date is of date type, but it has only day part, no time part, like '2016-02-25 00:00:00', this column has about 1000 unique values, and these values spread evenly among the records in the table. col_char1 is of varchar2 type, it has about 30 unique values, and these values also spread evenly. col_char2 is also of varchar2 type, it has about 20 unique values, and these values spread evenly. where clause is like col_date >= to_date('2016-02-24 00:00:00') and col_char1 = 'VAL1' and col_char2 = 'VAL2'. The query result is about 3000 rows.
I created an index INDEX1 with col_date, col_char1 and col_char2, in the order col_date, col_char1 and col_char2.
The execution plan is index skip scan using INDEX1. I don't know why it uses skip scan instead of range scan. I think skip scan should make this query very slow because the first column (col_date) in the index has so many distinct values.
The best index for the conditions you have in your question is a composite index on (col_char1, col_char2, col_date) (or the first two keys can be reversed).
If you don't have this index, but have a similar index, then I think a skip-scan will be used.

How to list distinct keys of an index?

user_indexes table has a column named 'distinct keys'. Does this value represent the number of distinct keys in the column indexed. In that case, is there a way to list all those keys ?
Does this value represent the number of distinct keys in the column indexed.
Yes, it does represent the number of distinct indexed values.
In that case, is there a way to list all those keys ?
You'll have to manually execute SELECT DISTINCT column_name FROM table_name to get list of distinct values. There is no system view, which stores the distinct values associated to an indexed column.
Since you're interested in the distinct values in an index, you would be better off running a query like this:
SELECT DISTINCT column_name FROM table_name WHERE column_name IS NOT NULL;
This is very likely to use the index to return the distinct values very quickly, without having to do a full table scan and a sort.
(Note: if the column already has a validated NOT NULL constraint, you won't need the "IS NOT NULL" where clause).

Alternate method for PIVOT - IN with sub-query support

As per oracle documentation, PIVOT function doesn't support sub-query in the "IN" clause but it is possible in the PIVOT XML function.
E.g.
SELECT *
FROM table_name
PIVOT
(
SUM(column_name_1)
FOR [column_name_2] IN (['Output_Column1'],['Output_Column2'])
)
AS aliasName
I need to replace the ['Output_Column1'],['Output_Column2'] with sub-query.
Is there some other function equivalent to PIVOT where we can supply sub-query instead hard coding the entire output columns or even in the PIVOT function itself?.
No, the number of columns must be known at parse time. For PIVOT XML there is no problem because such query returns only one column.

Oracle select max id from table returns null value

I have the query:
SELECT MAX(prod_id) FROM products;
It returns the maximum value if there are records. But, if I truncate table and run the same query I am unable to get the max id.
In case you want to query a table's column and suspect that the max function may return null, then you can return 0 in case null is encountered
SELECT NVL(MAX(P.PROD_ID), 0) AS MAX_VAL
FROM PRODUCTS P
This will return at least 0 , if no value is encountered for the column that you mention ()
Yes, by truncating the table you have removed all data in it, with no need for a commit. Therefore there is no data in the table and the max of nothing is nothing.
If you truncate the table, there are no rows left in the table. By definition, Max() returns NULL when run against an empty table.... or did I miss something here?
As Gerald P. Wright commented to an answer, if id is generated by a sequence, you can use it to find the value.
But
SELECT prod_id_seq.currval FROM DUAL
won't work, because currval works only in the session where you fetched a value with currval.
so,
SELECT prod_id_seq.nextval FROM DUAL
can be an workaround for you, but would be a realy, realy BAD solution(if you get the id with this several times you'll get incremented values).

Resources