Oracle PIVOT with subquery (without XML clause) - oracle

Oracle 19.3 on Win2019
Looking for a solution to pivot data based on the subquery. I looked for examples, but all I found is the "pivot xml" solution, which returns xml-formated column.
Here is my query:
with assign_data as
(
select --*
style_id
,color_id
,size_id
,in_whse_date
,sum(pd2_assign_so_quantity) qty
from pd2_assignment
where business_unit_id = '81'
and style_id = 'Y186F3D'
and color_id = '035Y'
and property_mark = '8FQR'
group by
style_id
,color_id
,size_id
,in_whse_date
order by size_id
)
select * from assign_data
pivot XML (
sum(qty) for (in_whse_date) in ( select distinct in_whse_date from assign_data)
)
Inner query produces this:
Pivot XML produces this:
Question: Is it possible to generate PIVOT with columns from a subquery that are not in xml format?
If not, is there another way to simulate this pivot behavior?

Related

Where Not In using query builder

Similary with this question I need to execute the following Sql query:
SELECT COUNT(*) from table where column NOT IN (SELECT table2.id from table2 where table2.someanothercolumn >0 );
Using Eloquent's query builder, therefore I tried the following (Model Table maps into table table and Model TableTwo maps into table table2):
$enties = Table::where('id',function($q){
$q->from('table2')->select('id')->where('someanothercolumn','>',0);
})->count();
But on the cide above how I can Place the NOT IN clause?
Your answer is in the following snippet of code:
$enties = Table::whereNotIn('id',function($q){
$q->from('table2')->select('id')->where('someanothercolumn','>',0);
})->count();
In other words just use the whereNotIn.

Query to get Unique Indexes having NOT NULL columns - Oracle

Currently I am trying to find all the unique indexes defined in a table which are NOT NULL for Oracle database. What I mean by that is, Oracle allows creating unique indexes on columns which are even defined as NULL.
So if my table has two unique indexes, I want to retrieve the particular unique index which is having all the columns having the NOT NULL constraints.
I did come up with this query:
select ind.index_name, ind_col.column_name, ind.index_type, ind.uniqueness
from sys.dba_indexes ind
inner join sys.dba_ind_columns ind_col on ind.owner = ind_col.index_owner and ind.index_name = ind_col.index_name
where ind.owner in ('ISADRM') and ind.table_name in ('TH_RHELOR') and ind.uniqueness IN ('UNIQUE')
The above query is giving me all the unique indexes with the associated columns, but I am not sure, how should I join the above query with ALL_TAB_COLS which has the NULLABILITY data for all the columns of a table.
I tried joining this table with indexes and tried subquery as well, but not getting appropriate results.
Hence, would request you to please comment on same.
Analytic functions and inline views can help.
The analytic functions let you return detailed data but also create a summary on that data, based on separate windows. The detailed results include index owner, index name, and column name, but the counts are only per index owner and index name.
The first inline view joins the three tables, returns the detailed information, and has analytic functions to generate the count of all columns and the count of all nullable columns. The second inline view only selects rows where those two counts are equal.
--Unique indexes and columns where every column is NOT NULL.
select owner, index_name, column_name
from
(
--All relevant columns and counts of columns and not null columns.
select
dba_indexes.owner,
dba_indexes.index_name,
dba_tab_columns.column_name,
dba_tab_columns.nullable,
count(*) over (partition by dba_indexes.owner, dba_indexes.index_name) total_columns,
sum(case when nullable = 'N' then 1 else 0 end)
over (partition by dba_indexes.owner, dba_indexes.index_name) total_not_null_columns
from dba_indexes
join dba_ind_columns
on dba_indexes.owner = dba_ind_columns.index_owner
and dba_indexes.index_name = dba_ind_columns.index_name
join dba_tab_columns
on dba_ind_columns.table_name = dba_tab_columns.table_name
and dba_ind_columns.column_name = dba_tab_columns.column_name
where dba_indexes.owner = user
and dba_indexes.uniqueness = 'UNIQUE'
order by 1,2,3
)
where total_columns = total_not_null_columns
order by 1,2,3;
Analytic functions and inline views are tricky but they're very powerful once you learn how to use them.

Vertica subquery with limit

I found problem in writing subquery with limit 1 to get the top record.
Here is my problem example.
Table Master(id,set)
Table Detail(id,set,code)
i am trying to get the latest code for each set in Master table.
Following is the query which i tried but got an error that limit 1 is not supported for correlated subqueries and it should contain GROUP By clause.
select id,set,(select code from detail where set=master.set order by id desc limit 1) from master;
And the result wolud be like
please help me if this is wrong way, i am new to this vertica database.
thnk you.
I'm not sure about that particular error, but you can use the rank() analytic function to produce results like this:
select id, set, code from (
select M.id, D.set, D.code, rank() over (partition by D.set order by D.id desc) as rank
from detail as D
right outer join master as M
on D.set = M.set) as ranks
where rank = 1
order by id;
The inner subquery uses the rank() function to assign a rank to each row within a set. The outer query just picks out rows with rank 1.

Need to select column from subquery into main query

I have a query like below - table names etc. changed for keeping the actual data private
SELECT inv.*,TRUNC(sysdate)
FROM Invoice inv
WHERE (inv.carrier,inv.pro,inv.ndate) IN
(
SELECT carrier,pro,n_dt FROM Order where TRUNC(Order.cr_dt) = TRUNC(sysdate)
)
I am selecting records from Invoice based on Order. i.e. all records from Invoice which are common with order records for today, based on those 3 columns...
Now I want to select Order_Num from Order in my select query as well.. so that I can use the whole thing to insert it into totally seperate table, let's say orderedInvoices.
insert into orderedInvoices(seq_no,..same columns as Inv...,Cr_dt)
(
SELECT **Order.Order_Num**, inv.*,TRUNC(sysdate)
FROM Invoice inv
WHERE (inv.carrier,inv.pro,inv.ndate) IN
(
SELECT carrier,pro,n_dt FROM Order where TRUNC(Order.cr_dt) = TRUNC(sysdate)
)
)
?? - how to do I select that Order_Num in main query for each records of that sub query?
p.s. I understand that trunc(cr_dt) will not use index on cr_dt (if a index is there..) but I couldn't select records unless I omit the time part of it..:(
If the table ORDER1 is unique on CARRIER, PRO and N_DT you can use a JOIN instead of IN to restrict your records, it'll also enable you to select whatever data you want from either table:
select order.order_num, inv.*, trunc(sysdate)
from Invoice inv
join order ord
on inv.carrier = ord.carrier
and inv.pro = ord.pro
and inv.ndate = ord.n_dt
where trunc(order.cr_dt) = trunc(sysdate)
If it's not unique then you have to use DISTINCT to deduplicate your record set.
Though using TRUNC() on CR_DT will not use an index on that column you can use a functional index on this if you do need an index.
create index i_order_trunc_cr_dt on order (trunc(cr_dt));
1. This is a really bad name for a table as it's a keyword, consider using ORDERS instead.

Why is "group by" giving only one column as output?

I have a table something like this:
ID|Value
01|1
02|4
03|12
01|5
02|14
03|22
01|9
02|32
02|62
01|13
03|92
I want to know how much progress have each id made (from initial or minimal value)
so in sybase I can type:
select ID, (value-min(value)) from table group by id;
ID|Value
01|0
01|4
01|8
01|12
02|0
02|10
02|28
02|58
03|0
03|10
03|80
But monetdb does not support this (I am not sure may be cz it uses SQL'99).
Group by only gives one column or may be average of other values but not the desired result.
Are there any alternative to group by in monetdb?
You can achieve this with a self join. The idea is that you build a subselect that gives you the minimum value for each id, and then join that to the original table by id.
SELECT a.id, a.value-b.min_value
FROM "table" a INNER JOIN
(SELECT id, MIN(value) AS min_value FROM "table" GROUP BY id) AS b
ON a.id = b.id;

Resources