Naming conventions with pivot function - oracle

The code I'm using is below. The issue is that the items I'm pivoting on go last in the naming convention. I.E null_pdiv_spend, null_pdiv_visits. I would like to have the naming convention be spend_null_pdiv to coincide with the rest of my tables. Please advise.
pivot(
count(x) as visits,
sum(y) as spend,
sum(c) as items,
sum(b) as mkdn
for pdiv_cd in (
'###' as null_pdiv,
'010' as hbags_acc,
'011' as fine_jewelry,
'070' as pdiv_70
)
)

You can add another level of subquery, and rename the columns with aliases:
select null_pdiv_spend as spend_null_pdiv,
null_pdiv_visits as visits_null_pdiv,
...
from (
select *
from (
...
)
pivot(count(x) as visits, sum(y) as spend, sum(c) as items, sum(b) as mkdn
for (pdiv_cd) in (
'###' as null_pdiv,
'010' as hbags_acc,
'011' as fine_jewelry,
'070' as pdiv_70
)
)
)
That lets you modify the order of the columns in the result set too, if that matters to you.

Related

In DAX, is it possible to check if value exists in another table using measure instead of calculated column?

I'm hoping to create a measure of distinct count of a customer column, on the condition if customers in this column does not exist in another table's customer column.
I know I can create a calculated column checking if the customer exists, and then use the calculate function filtering out those who do exist. But is it possible to achieve this without creating the calculated column?
Please note this is in Power Pivot, not Power BI so I can't really use 'treatas' or 'in'. Thanks a lot.
Assuming tables named Table1 and Table2:
MyMeasure :=
VAR T2Customer =
VALUES( Table2[Customer] )
RETURN
CALCULATE(
DISTINCTCOUNT( Table1[Customer] ),
NOT (
CONTAINSROW(
T2Customer,
Table1[Customer]
)
)
)
Yes, You can achieve it using EXCEPT()function:
Let's say that we have 2 tables like this:
Customer_Table1:
Customer_Table2:
Now we can use this measure to achieve our result:
CountOfDistinctCusts =
COUNTROWS (
EXCEPT (
VALUES ( Customer_Table1[Customer] ),
VALUES ( Customer_Table2[Customer] )
)
)
If we test the code:

Selecting only a sequence

I would like to select in my table only a part after i read 00006 and stop selecting when i read the next pattern 00XXX .(here it's 00040 but it's could be an another number )
00006
123456
456789
123789
00040
125478
547896
454623
519846
00001
....
Here , for example i would like to get only these values with a select :
123456
456789
123789
How is the way to obtain that ? I dont find any clue.
Thanks for your help.
ps: i have no rights for transform the table where i select
With the solution of Charles :
with marker as (
select rownumber() over() as rowno
, rrn(t) as recno, cast(substr(YYYYYY, 1, 5)as integer) as markvalue
from fap1t010.£$ZZZZZZ t
where substr(YYYYYY, 1, 5) like ('00___')
), dataa as (
select rrn(t) as recno, cast(substr(YYYYYY, 1, 6)as integer) as datavalue
from fap1t010.£$ZZZZZZ t
where substr(YYYYYY, 1, 5) NOT like ('00006')
and substr(YYYYYY, 13, 1) ='C'
), ranges as(
select a.markvalue
, a.recno as startrec
, b.recno as endrec
from marker A join marker B
on b.rowno = a.rowno +1
)
select distinct d.datavalue
from ranges R join dataa D
on d.recno between r.startrec and r.endrec
where r.markvalue = 00006
Wow...that's an ugly request.
But it can be done:
with marker as (
select rownumber() over() as rowno
, rrn(t) as recno, myfld as markvalue
from dtcwilt.temp t
where myfld like ('00___ ')
), data as (
select rrn(t) as recno, myfld as datavalue
from dtcwilt.temp t
where myfld NOT like ('00___ ')
), ranges as(
select a.markvalue
, a.recno as startrec
, b.recno as endrec
from marker A join marker B
on b.rowno = a.rowno +1
)
select d.datavalue
from ranges R join data D
on d.recno between r.startrec and r.endrec
where r.markvalue = '00006';
If you have a large data set, performance isn't going to be all that great; there's probably room for improvement. But the above is at least easy to understand.
If you happen to be on the latest version 7.3 of IBM i, you could probably simplify the statement by making use of the new LEAD() and/or LAG() functions. But I don't have 7.3 to test on.

Passing a parameter to a WITH clause query in Oracle

I'm wondering if it's possible to pass one or more parameters to a WITH clause query; in a very simple way, doing something like this (taht, obviously, is not working!):
with qq(a) as (
select a+1 as increment
from dual
)
select qq.increment
from qq(10); -- should get 11
Of course, the use I'm going to do is much more complicated, since the with clause should be in a subquery, and the parameter I'd pass are values taken from the main query....details upon request... ;-)
Thanks for any hint
OK.....here's the whole deal:
select appu.* from
(<quite a complex query here>) appu
where not exists
(select 1
from dual
where appu.ORA_APP IN
(select slot from
(select distinct slots.inizio,slots.fine from
(
with
params as (select 1900 fine from dual)
--params as (select app.ora_fine_attivita fine
-- where app.cod_agenda = appu.AGE
-- and app.ora_fine_attivita = appu.fine_fascia
--and app.data_appuntamento = appu.dataapp
--)
,
Intervals (inizio, EDM) as
( select 1700, 20 from dual
union all
select inizio+EDM, EDM from Intervals join params on
(inizio <= fine)
)
select * from Intervals join params on (inizio <= fine)
) slots
) slots
where slots.slot <= slots.fine
)
order by 1,2,3;
Without going in too deep details, the where condition should remove those records where 'appu.ORA_APP' match one of the records that are supposed to be created in the (outer) 'slots' table.
The constants used in the example are good for a subset of records (a single 'appu.AGE' value), that's why I should parametrize it, in order to use the commented 'params' table (to be replicated, then, in the 'Intervals' table.
I know thats not simple to analyze from scratch, but I tried to make it as clear as possible; feel free to ask for a numeric example if needed....
Thanks

recursive cte working very slow

I want to Group the rows based on certain columns, i.e. if data is same in these columns in continuous rows, then assign same Group Number to them, and if its changed, assign new one. This become complex as the same data in the columns could appear later in some other rows, so they have to be given another Group Number as they are not in continuous rows with previous group.
I used cte for this purpose and it is giving correct output also, but is so slow that iterating over 75k+ rows takes about 15 minutes. The code I used is:
WITH
cte AS (SELECT ROW_NUMBER () OVER (ORDER BY Patient_ID, Opnamenummer, SPECIALISMEN, Opnametype, OntslagDatumTijd) AS RowNumber,
Opnamenummer, Patient_ID, AfdelingsCode, Opnamedatum, Opnamedatumtijd, Ontslagdatum, Ontslagdatumtijd, IsSpoedopname, OpnameType, IsNuOpgenomen, SpecialismeCode, Specialismen
FROM t_opnames)
SELECT * INTO #ttt FROM cte;
WITH cte2 AS (SELECT TOP 1 RowNumber,
1 AS GroupNumber,
Opnamenummer, Patient_ID, AfdelingsCode, Opnamedatum, Opnamedatumtijd, Ontslagdatum, Ontslagdatumtijd, IsSpoedopname, OpnameType, IsNuOpgenomen, SpecialismeCode, Specialismen
FROM #ttt
ORDER BY RowNumber
UNION ALL
SELECT c1.RowNumber,
CASE
WHEN c2.Afdelingscode <> c1.Afdelingscode
OR c2.Patient_ID <> c1.Patient_ID
OR c2.Opnametype <> c1.Opnametype
THEN c2.GroupNumber + 1
ELSE c2.GroupNumber
END AS GroupNumber,
c1.Opnamenummer,c1.Patient_ID,c1.AfdelingsCode,c1.Opnamedatum,c1.Opnamedatumtijd,c1.Ontslagdatum,c1.Ontslagdatumtijd,c1.IsSpoedopname,c1.OpnameType,c1.IsNuOpgenomen, SpecialismeCode, Specialismen
FROM cte2 c2
JOIN #ttt c1 ON c1.RowNumber = c2.RowNumber + 1
)
SELECT *
FROM cte2
OPTION (MAXRECURSION 0) ;
DROP TABLE #ttt
I tried to improve performance by putting output of cte in a temp table. That increased the performance, but still its too slow. So, how can I increase the performance of this code to run it under 10 seconds for 75k+ records? The output before cancelling the query is: Screenshot. As visible from the image, data is same in columns Afdelingscode,Patient_ID and Opnametype in RowNumber 3,5 and 6, but they have different GroupNumber because of concurrency of the rows.
Without data its not that easy to test but i would try first to not use temporary table and just use both cte from start to end, ie;
;WITH
cte AS (...),
cte2 AS (...)
select * from cte2
OPTION (MAXRECURSION 0);
Without knowing indices etc... for instance, you do a lot of ordering in the first cte. Is this supported by indices (or one multicolumn index) or not?
Without the data i don't have the option to play with it but looking at this:
CASE
WHEN c2.Afdelingscode <> c1.Afdelingscode
OR c2.Patient_ID <> c1.Patient_ID
OR c2.Opnametype <> c1.Opnametype
THEN c2.GroupNumber + 1
ELSE c2.GroupNumber
i would try to take a look at partition by statement in row_number
So try to run this:
WITH
cte AS (
SELECT ROW_NUMBER () OVER (PARTITION BY Afdelingscode , Patient_ID ,Opnametype ORDER BY Patient_ID, Opnamenummer, SPECIALISMEN, Opnametype, OntslagDatumTijd ) AS RowNumber,
Opnamenummer, Patient_ID, AfdelingsCode, Opnamedatum, Opnamedatumtijd, Ontslagdatum, Ontslagdatumtijd, IsSpoedopname, OpnameType, IsNuOpgenomen
FROM t_opnames)

Trying to select all records where two fields are distinct (but the rest don't have to be)

I have a table that has 14 columns in it. These columns are color, type, ft, date, count, etc. What I need is to select all distinct records of id and type with the most recent date. So, for example...
color------type-----------date
red--------work-----------01/01/01
red---------play----------02/02/02
red---------play----------03/03/03
In this case, I want to return red, work, 01/01/01 and red, play 03/03/03. Hopefully this makes sense. I've tried different combinations of select unique and select distinct and group bys, and I haven't been able to come up with anything.
Here is the SQL statement I'm trying:
select distinct
chock_id,
roll_type,
max(chock_service_dt),
chock_id_dt,
chock_seq_num,
chock_service_cmnt,
total_rolled_lineal_ft,
total_rolled_tons,
chock_usage_cnt,
chock_insert_dt,
record_modify_dt,
next_chock_service_dt_act,
previous_alarm_value,
upload_complete_yn
from
tp07_chock_summary_row
group by
chock_id,
roll_type,
chock_service_dt,
chock_id_dt,
chock_seq_num,
chock_service_cmnt,
total_rolled_lineal_ft,
total_rolled_tons,
chock_usage_cnt,
chock_insert_dt,
record_modify_dt,
next_chock_service_dt_act,
previous_alarm_value,
upload_complete_yn;
Here's a screenshot. Like I said in a comment below, like in rows 2 and 4, I can't have multiple records with the same chock_id and roll_type.
Given your new requirements, which you did not explain initially, this should do it:
select
chock_id,
roll_type,
chock_service_dt,
chock_id_dt,
chock_seq_num,
chock_service_cmnt,
total_rolled_lineal_ft,
total_rolled_tons,
chock_usage_cnt,
chock_insert_dt,
record_modify_dt,
next_chock_service_dt_act,
previous_alarm_value,
upload_complete_yn
from (
select
chock_id,
roll_type,
chock_service_dt,
chock_id_dt,
chock_seq_num,
chock_service_cmnt,
total_rolled_lineal_ft,
total_rolled_tons,
chock_usage_cnt,
chock_insert_dt,
record_modify_dt,
next_chock_service_dt_act,
previous_alarm_value,
upload_complete_yn,
row_number() over (
partition by chock_id, roll_type
order by chock_service_dt desc
) rn
from
tp07_chock_summary_row
) where rn = 1
select color, type, max(date)
from ...
group by color, type
select
color,
type,
max(date)
from
yourtable
group by
color,
type

Resources