how to get the most updated result in oracle - oracle

I have a query, get the results for different people, but for every people, they have different results, how can i get oldest result for each people, the following pic is for one specific people.

select <<your fields>>
from (select t.*, row_number(partition by <<person_id>> order by OLD_ACTIVE_DT desc) as rn
from <<your query>> t) vw
where vw.rn = 1

Related

Function returning Last record

I don't often use ORACLE PL/SQL by the way but i need to understand what if anything in this function created by someone else
in the company before me is wrong as for it is not returning the latest record i've been told. I found out in some other forum issues that they
suggested to use the max(dateColumn) instead of "row_numer = 1" for example but not quite sure how to and where to incorporate that.
-- Knowing that --
We use Oracle version 12,
CustomObjectTypeA is an custom Oracle OBJECT TYPE defined by some old employee not longer in here,
V_OtherView is of Table_Mnd type beeing defined by some old employee not longer in here,
V_ABC_123 is a view created by some old employee not longer in here as well.
CREATE OR REPLACE FUNCTION F_TABLE_APPROVED (NUMBER_F_UPD number, NUMBER_F_GET VARcHAR2)
RETURN Table_Mnd
IS
V_OtherView Table_Mnd
BEGIN
SELECT CustomObjectTypeA (FromT.NUMBER_F,
FromT.OP_CODE,
FromT.CATG_CODE,
FromT.CATG_NAME,
FromT.CATG_SORT,
FromT.ORG_CODE,
FromT.ORG_NAME
FromT.DATA_ENTRY_VALID,
FromT.NUMBER_RECEIVED,
FromT.YEAR_1,
FromT.YEAR_2)
BULK COLLECT INTO V_OtherView
FROM (SELECT NUMBER_F,
OP_CODE,
CATG_CODE,
CATG_NAME,
CATG_SORT,
ORG_CODE,
ORG_NAME
DATA_ENTRY_VALID,
NUMBER_RECEIVED,
YEAR_1,
YEAR_2,
ROW_NUMBER() OVER (PARTITION BY BY ORG_CODE ORDER BY NUMBER_RECEIVED DESC, LOAD_DATE DESC) AS ROW_NUMBER
FROM V_ABC_123
WHERE NUMBER_F = NUMBER_F_UPD AND DATA_ENTRY_VALID <> 'OnGoing'
AND LOAD_DATE >= (SELECT sysdate-10 FROM dual)
AND LOAD_DATE <= (SELECT DISTINCT LOAD_DATE
FROM V_ABC_123
WHERE NUMBER_RECEIVED = NUMBER_F_GET)) FromT
WHERE FromT.ROW_NUMBER=1;
RETURN V_OtherView;
END F_TABLE_APPROVED;
The important bits of the query are:
SELECT ...
FROM (select ...,
ROW_NUMBER()
OVER (PARTITION BY ORG_CODE
ORDER BY NUMBER_RECEIVED DESC,
LOAD_DATE DESC) AS ROW_NUMBER
...) FromT
WHERE FromT.ROW_NUMBER = 1;
The "ROW_NUMBER" column is computed according to the following window clause:
PARTITION BY ORG_CODE
ORDER BY NUMBER_RECEIVED DESC, LOAD_DATE DESC
Which means that for each ORG_CODE, it will sort all the records by NUMBER_RECEVED,LOAD_DATE in descending order. Note that if the columns are Oracle DATEs, they will only be accurate to the nearest second; so if there are multiple records with date/times in the exact same 1-second interval, this sort order will not be guaranteed unique. The logic of ROW_NUMBER will therefore pick one of them arbitrarily (i.e. whichever record happens to be emitted first) and assign it the value "1", and this will be deemed the "latest". Subsequent executions of the same SQL could (in theory) return a different record.
The suspicious part is NUMBER_RECEIVED which sounds like it's a number, not a date? Sorting by this means that the records with the highest NUMBER_RECEIVED will be preferred. Was this intentional?
I'm not sure why the PARTITION is there, this would cause the query to return one "latest" record for each value of ORG_CODE that it finds. I can only assume this was intentional.
The problem is that the query can only determine the "latest record" as well as it can based on the data provided to it. In this case, it's possible the data is simply not granular enough to be able to decide which record is the actual "latest" record.

Select Earliest Invoice Date and Max Distribution Line Amount per Supplier

Using Oracle, PSQL, I am trying to figure out the earliest invoice date for each supplier. That would be simple enough, but I am also trying to figure out the max distribution line on the earliest invoice so I can determine what segment of the business the invoice belongs to. Segment is determined by SEGMENT_NUMBER in the example below. I know a sub query or multiple sub queries are needed here with a group by clause but I am at a loss. The syntax below is not even close, but I wanted to provided something for feedback.
SELECT
SUPPLIER_ID,
INVOICE_NUMBER,
SEGMENT_NUMBER,
MIN(INVOICE_DATE) as EARLIEST_INV_DATE,
MAX(DISTRIBUTION_AMOUNT) as MAX_DIST_LINE
FROM INVOICE_DIST
Use Analytical function like RANK().
SELECT SUPPLIER_ID,
INVOICE_NUMBER,
SEGMENT_NUMBER,
INVOICE_DATE,DISTRIBUTION_AMOUNT
(SELECT SUPPLIER_ID,
INVOICE_NUMBER,
SEGMENT_NUMBER,
INVOICE_DATE,DISTRIBUTION_AMOUNT,
RANK() OVER(PARTITION BY SUPPLIER_ID ORDER BY INVOICE_DATE,DISTRIBUTION_AMOUNT DESC) POSITION FROM INVOICE_DIST) TBL WHERE POSITION=1;

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

Oracle Daily count/average over a year

I'm pulling two pieces of information over a specific time period, but I would like to fetch the daily average of one tag and the daily count of another tag. I'm not sure how to do daily averages over a specific time period, can anyone provide some advice? Below were my first ideas on how to handle this however to change every date would be annoying. Any help is appreciated thanks
SELECT COUNT(distinct chargeno), to_char(chargetime, 'mmddyyyy') AS chargeend
FROM batch_index WHERE plant=1 AND chargetime>to_date('2012-06-18:00:00:00','yyyy-mm-dd:hh24:mi:ss')
AND chargetime<to_date('2012-07-19:00:00:00','yyyy-mm-dd:hh24:mi:ss')
group by chargetime;
The working version of the daily sum
SELECT to_char(bi.chargetime, 'mmddyyyy') as chargtime, SUM(cv.val)*0.0005
FROM Charge_Value cv, batch_index bi WHERE cv.ValueID =97
AND bi.chargetime<=to_date('2012-07-19','yyyy-mm-dd')
AND bi.chargeno = cv.chargeno AND bi.typ=1
group by to_char(bi.chargetime, 'mmddyyyy')
seems like in the first one you want to change the group to the day - not the time... (plus i dont think you need to specify all those 0's for seconds..)
SELECT COUNT(distinct chargeno), to_char(chargetime, 'mmddyyyy') AS chargeend
FROM batch_index WHERE plant=1 AND chargetime>to_date('2012-06-18','yyyy-mm-dd')
AND chargetime<to_date('2012-07-19','yyyy-mm-dd')
group by to_char(chargetime, 'mmddyyyy') ;
not 100% I'm following your question, but if you just want to do aggregates (sums, avg), then do just that. I threw in the rollup just in case that is what you were looking for
with fakeData as(
select trunc(level *.66667) nr
, trunc(2*level * .33478) lvl --these truncs just make the doubles ints
,trunc(sysdate+trunc(level*.263784123)) dte --note the trunc, this gets rid of the to_char to drop the time
from dual
connect by level < 600
) --the cte is just to create fake data
--below is just some aggregates that may help you
select sum(nr) daily_sum_of_nr
, avg(nr) daily_avg_of_nr
, count(distinct lvl) distinct_lvls_per_day
, count(lvl) count_of_nonNull_lvls_per_day
, dte days
from fakeData
group by rollup(dte)
--if you want the query to supply a total for the range, you may use rollup ( http://psoug.org/reference/rollup.html )

PL SQL concatenate 2 resultsets

I need to get the result of concatenating 2 similar querys' resulsets. For some reason had to split the original query in 2, both with their corresponding order by clause. Should be something like (this is an oversimplification of the original queries)
Query1: Select name, age from person where age=10
Resultset1:
Person1, 10
Person3, 10
Query2: Select name, age from person where age=20
Resultset1:
Person2, 20
Person6, 20
The expected result:
Person1, 10
Person3, 10
Person2, 20
Person6, 20
I can not simply use Query1 UNION Query2.
Below the 2 original querys:
(#1)
select cp.CP_ID, cpi.CI_DESCRIPCION, cp.CP_CODIGOJERARQUIZADO, cp.CP_ESGASTO as gasto, cp.CP_CONCEPTOPADRE, LEVEL
from TGCCP_ConceptoPagoIng cp
left join tgcci_ConceptoPagoIngIdioma cpi on cpi.CI_IDCONCEPTOPAGOING = cp.CP_ID and cpi.CI_IDIDIOMA = 1
start with ((CP_CONCEPTOPADRE is null) and (**cp.CP_ESGASTO = 1**))
connect by prior cp.CP_ID = cp.CP_CONCEPTOPADRE
order siblings by CP_CODIGOJERARQUIZADO
(#2)
select cp.CP_ID, cpi.CI_DESCRIPCION, cp.CP_CODIGOJERARQUIZADO, cp.CP_ESGASTO as gasto, cp.CP_CONCEPTOPADRE, LEVEL
from TGCCP_ConceptoPagoIng cp
left join tgcci_ConceptoPagoIngIdioma cpi on cpi.CI_IDCONCEPTOPAGOING = cp.CP_ID and cpi.CI_IDIDIOMA = 1
start with ((CP_CONCEPTOPADRE is null) and (**cp.CP_ESGASTO = 2**))
connect by prior cp.CP_ID = cp.CP_CONCEPTOPADRE
order siblings by CP_CODIGOJERARQUIZADO
I think you want a
select * from ( first query )
UNION ALL
select * from ( second query )
Where first query and second query are the queries from above, so you are turning them into subqueries, thus preserving the order by clauses.
OK, well, I'm not fully certain why you need it this way, but if Oracle won't allow you to do a UNION, or it screws up the ordering when you do, I would try creating a pipelined table function.
An example here
Basically, you'd create a procedure that ran both queries, first one, then the other, putting the results of each into the returned dataset.
It looks like you are looking for a MULTISET UNION. Which can only be used from version 10 upwards.
Regards,
Rob.
You could combine your queries as subqueries and do a single order by on the outer query:
select * from (
<query 1 with its order by>
UNION ALL
<query 2 with its order by>
)
order by column1, column2;
Alternatively, you can implement in PL/SQL the equivalent of a sort merge join with two cursors, but that's unnecessarily complicated.
this solution works perfectly:
select * from ( first query )
UNION ALL
select * from ( second query )
I appreciate everyone that have taken the time to answer.
regards.
For your example:
Select name, age from person where age in (10,20)
or
Select name, age from person where age = 10 or age = 20
However I'm guessing this is not what you need :)

Resources