How to combine two different queries to get one output - sql

I have created the below two queries to see changes within table per_assignments and per_supervisor for columns locat_id,org_id, mng_id.
with asg_loc_dep as (
select person_id,
prev_start_dt,
start_dt,
loc_old,
loc_new,
org_new,
org_old
from (
select person_id,
locat_id loc_new,
org_id org_new,
start_dt,
lag(locat_id) over (partition by person_id order by start_dt) loc_old,
lag(org_id) over (partition by person_id order by start_dt) org_old,
lag(start_dt) over (partition by person_id order by start_dt) prev_start_dt,
case start_dt when 1 + lag(end_dt) over (partition by person_id order by start_dt)
then 1 end flag
from per_assignments
)
where flag = 1
and (loc_new <> loc_old or org_new <> org_old)
)
with asg_asg as (
select person_id,
prev_start_dt,
start_dt,
new_mgr,
mngid_old
from (
select person_id,
mng_id new_mgr,
start_dt,
lag(mng_id) over (partition by assignment_id order by start_dt) mngid_old,
lag(start_dt) over (partition by assignment_id order by start_dt) prev_start_dt,
case start_dt when 1 + lag(end_dt) over (partition by assignment_id order by start_dt)
then 1 end flag
from per_supervisor
)
where flag = 1
and (mngid_old<>new_mgr)
)
I am getting the right results individually, is there a way to combine these two queries into one to get the below output structure :
person_id prev_start_dt start_dt loc_old loc_new org_new org_old mngid_old new_mgr
the common link between both these queries is the person_id. if i use union, what will i pass for the left out columns, also if for the same date -prev_start_dt and start_dt there is a change in loc_new and new_mgr, then it should come in 1 row. with union it will come in 2 rows.
sample fiddle in only the 1st query
https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=a3b74f9c4f8371ad23bbf53dcbe41f67
WITH loc_dep AS
(
SELECT person_id,
prev_start_dt,
start_dt,
--assignment_id,
loc_old,
loc_new,
org_old,
org_new
FROM (
SELECT person_id,
assignment_id,
location_id loc_new,
organization_id org_new,
effective_start_date start_dt,
Lag(location_id) OVER (partition BY person_id ORDER BY effective_start_date) loc_old,
Lag(organization_id) OVER (partition BY person_id ORDER BY effective_start_date) org_old,
Lag(effective_start_date) OVER (partition BY person_id ORDER BY effective_start_date) prev_start_dt,
CASE effective_start_date
WHEN 1 + Lag(effective_end_date) OVER (partition BY person_id ORDER BY effective_start_date) THEN 1
END flag
FROM per_all_assignments_m paam
WHERE paam.person_id = '300000010518043'
AND paam.system_person_type = 'EMP'
AND paam.assignment_status_type = 'ACTIVE'
AND paam.assignment_type = 'E' )
WHERE flag = 1
AND (
loc_new <> loc_old
OR org_new <> org_old)) ,
with mgr_compare AS
(
SELECT DISTINCT person_id,
prev_start_dt,
start_dt,
mngr_new,
mngr_old
FROM (
SELECT person_id,
manager_id mngr_new,
effective_start_date start_dt,
effective_end_date end_date,
lag(manager_id) OVER ( partition BY assignment_id ORDER BY effective_start_date) mngr_old,
lag(effective_start_date) OVER ( partition BY assignment_id ORDER BY effective_start_date) prev_start_dt,
CASE effective_start_date
WHEN 1 + lag(effective_end_date) OVER (partition BY assignment_id ORDER BY effective_start_date) THEN 1
END flag
FROM per_assignment_supervisors_f pasf
WHERE pasf.person_id = '300000010518043')
WHERE flag = 1
AND (
mngr_new <> mngr_old ))
SELECT mgr_compare.person_id
FROM mgr_compare,
loc_dep
WHERE loc_dep.person_id = mgr_compare.person_id

You could put both CTEs in the same query, and then join the results on person_id:
with
asg_loc_dep as (
select
person_id,
prev_start_dt,
start_dt,
loc_old,
loc_new,
org_new,
org_old
from ( ... )
where ...
),
asg_asg as (
select
person_id,
prev_start_dt,
start_dt,
new_mgr,
mngid_old
from (...)
where ...
)
select
l.person_id,
l.prev_start_dt,
l.start_dt,
l.loc_old,
l.loc_new,
l.org_new,
l.org_old,
a.mngid_old,
a.new_mgr
from asg_loc_dep l
inner join asg_asg a on a.person_id = l.person_id

Related

Getting category based on production shift

I have this query
with cte as(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY seq ORDER BY date_time) rn1,
ROW_NUMBER() OVER (PARTITION BY seq, output > 0
ORDER BY date_time) rn2
FROM myTable
;
select
seq,
date_time::date,
MIN(date_time) AS MinDatetime,
MAX(date_time) AS MaxDatetime,
SUM(output) AS sum_output
FROM cte cte
GROUP by
seq,
date_time::date ,
cntpr > 0,
rn1 - rn2
ORDER BY
seq,
MIN(date_time);
here's the result:
what I would like to do is to join my result to this master table
enter image description here
and the expected result will be MinDatetime and MaxDatetime among my master table's start and end shift to show the shift information, like this:
enter image description here
Any help would be very appreciated.. thank you!
This is the solution I came up with:
select seq, shift, start_shift, end_shift, MinDateTime, MaxDateTime
from
(
select
seq,
MIN(date_time) AS MinDatetime,
MAX(date_time) AS MaxDatetime,
SUM(output) AS sum_output
FROM cte cte
GROUP by
seq
ORDER BY
seq,
MIN(date_time::date)) t
join mstr
on
CASE
WHEN start_shift < end_shift THEN (MinDateTime::time between start_shift and end_shift) OR (MaxDateTime::time between start_shift and end_shift)
ELSE (MinDateTime::time >= start_shift) OR
(MaxDateTime::time >= start_shift) OR
(MinDateTime::time <= end_shift) OR
(MaxDateTime::time <= end_shift)
END
ORDER BY seq;
Fiddle: https://www.db-fiddle.com/f/4jyoMCicNSZpjMt4jFYoz5/4208
Explanation: I get the groups, join them with master table on interval matching.

SQL QUERY to get previous date

PERIOD_SERV
PERSON_NUMBER DATE_sTART PERIOD_ID
10 06-JAN-2020 192726
10 04-APR-2019 12827
11 01-FEB-2021 282726
11 09-APR-2018 827266
For each person_number I want to add a column with previous date start. When i am using the below query, it is giving me repeated rows.
I want to get only row, with an additional column of the most recent "last date_start". For example -
PERSON_NUMBER DATE_sTART PERIOD_ID PREVIOUS_DATE
10 06-JAN-2020 192726 04-APR-2019
11 01-FEB-2021 282726 09-APR-2018
I am using the below query but getting two rows,
SELECT person_number,
period_id AS pv_period_id,
LAG(date_start) OVER ( PARTITION BY person_number ORDER BY date_start) AS previous_date
FROM period_serv
You can restrict the set of rows in the outer query
select person_number, pv_period_id, PREVIOUS_DATE
from (
select person_number,
PERIOD_ID pv_period_id,
lag(date_start) OVER ( partition BY person_number order by DATE_sTART ) PREVIOUS_DATE ,
row_number() OVER ( partition BY person_number order by DATE_sTART desc) rn
from period_serv
) t
where rn = 1
One option is to use MAX(..) KEEP (DENSE_RANK ..) OVER (PARTITION BY ..) analytic function such as
WITH p AS
(
SELECT MAX(date_start) KEEP (DENSE_RANK FIRST ORDER BY date_start)
OVER (PARTITION BY person_number) AS previous_date,
p.*
FROM period_serv p
)
SELECT p.person_number, p.date_start, p.period_id, p.previous_date
FROM p
JOIN period_serv ps
ON ps.person_number = p.person_number
AND ps.period_id = p.period_id
WHERE ps.date_start != previous_date
Demo

I need to write a query to mark previous record as “Not eligible ” if a new record comes in within 30 days with same POS Order ID

I have a requirement to write a query to retrieve the records which have POS_ORDER_ID in the table with same POS_ORDER_ID which comes within 30days as new record with status 'Canceled', 'Discontinued' and need to mark previous POS_ORDER_ID record as it as not eligible
Table columns:
POS_ORDER_ID,
Status,
Order_date,
Error_description
A query containing MAX() and ROW_NUMBER() analytic functions might help you such as :
with t as
(
select t.*,
row_number() over (partition by pos_order_id order by Order_date desc ) as rn,
max(Order_date) over (partition by pos_order_id) as mx
from tab t -- your original table
)
select pos_order_id, Status, Order_date, Error_description,
case when rn >1
and t.status in ('Canceled','Discontinued')
and mx - t.Order_date <= 30
then
'Not eligible'
end as "Extra Status"
from t
Demo
Please use below query,
Select and validate
select POS_ORDER_ID, Status, Order_date, Error_description, row_number()
over(partition by POS_ORDER_ID order by Order_date desc)
from table_name;
Update query
merge into table_name t1
using
(select row_id, POS_ORDER_ID, Status, Order_date, Error_description,
row_number() over(partition by POS_ORDER_ID order by Order_date desc) as rnk
from table_name) t2
on (t1.POS_ORDER_ID = t2.POS_ORDER_ID and t1.row_id = t2.row_id)
when matched then
update
set
case when t2.rnk = 1 then 'Canceled' else 'Not Eligible';

What should be done to do multiple order by?

I want to sort by chart_num and DATE. However, the following results are printed out when aligned:
in this my code:
SELECT *
FROM (
SELECT id, chart_num, chart_name, MIN(DATE) AS DATE, amount, (COUNT(*) = 2) AS result, card_check
FROM (
(
SELECT id, hpd.chart_num AS chart_num, hpd.chart_name AS chart_name, hpd.visit AS DATE, card_amount_received AS amount, card_check_modify AS card_check
,row_number() over (PARTITION BY card_amount_received ORDER BY id) AS seqnum
FROM hospital_payment_data hpd
WHERE store_mbrno = '135790' AND card_amount_received > 0
)
UNION ALL (
SELECT id, ncd. chart_num AS chart_num, ncd. chart_name AS chart_name, DATE_FORMAT(ncd.tranDate,'%Y-%m-%d') AS DATA, amount, card_check_result AS card_check
,row_number() over (PARTITION BY amount ORDER BY id) AS seqnum
FROM noti_card_data ncd
WHERE (mbrNo = '135790' OR mbrNo = '135791') AND cmd ='승인'
)
) X
GROUP BY amount, seqnum
ORDER BY result DESC
) a
ORDER BY a.DATE DESC
The result I want is that the NULL value goes back to the latest DATE, and if there is a chart_num, I want to sort it in order of chart_num and DATE.
It feels like I'm missing something else with this question, but you can separate columns in the ORDER BY with a comma. It's not clear from your text whether you want dates grouped within the same chart_num or charts grouped within the same date, but if I guessed wrong you can just swap it.
Also, the ORDER BY result DESC is completely extra. It adds nothing to the results, and by removing it we can get rid of a whole level of nesting.
SELECT id, chart_num, chart_name, MIN(DATE) AS DATE, amount, (COUNT(*) = 2) AS result, card_check
FROM (
(
SELECT id, hpd.chart_num AS chart_num, hpd.chart_name AS chart_name, hpd.visit AS DATE, card_amount_received AS amount, card_check_modify AS card_check
,row_number() over (PARTITION BY card_amount_received ORDER BY id) AS seqnum
FROM hospital_payment_data hpd
WHERE store_mbrno = '135790' AND card_amount_received > 0
)
UNION ALL (
SELECT id, ncd.chart_num, ncd.chart_name, DATE_FORMAT(ncd.tranDate,'%Y-%m-%d'), amount, card_check_result
,row_number() over (PARTITION BY amount ORDER BY id) AS seqnum
FROM noti_card_data ncd
WHERE mbrNo IN ('135790', '135791') AND cmd ='승인'
)
) X
GROUP BY amount, seqnum
ORDER BY MIN(DATE), coalesce(chart_num,-1), result DESC
Dont order by result in the inner union all query.
Sort by chart_num and date in place of result.
So in place of
Order by result desc
use this:
Order by chart_num desc, DATE desc
Or,
in outer main query:
in place of
Order by a.DATE DESC
use
Order by a.chart_num desc, a.DATE desc
Hope it helps.!

SQL - How to perform a nested SELECT with multiple queries from the same table?

I wrote a nested select query and it's working correctly.
select user_id, transaction_id, t_timestamp
from (
select *, row_number() over (partition by (user_id || '*' || transaction_id) order by f_time asc) rownum
from transactionMetricsView
where metric_1 in (select metric_value
from main.metrics
where metric_key = 'metric_type_1')
)
where rownum = 1
But also the main.metrics table has an m_date field so I need to check if the date is within a given range.
But I'm not sure how to implement it correctly.
I think it should look something like the below query, but it's more like a pseudo-code now.
select user_id, transaction_id, t_timestamp
from (
select *, row_number() over (partition by (user_id || '*' || transaction_id) order by f_time asc) rownum
from transactionMetricsView
where metric_1 in (select metric_value
from main.metrics
where metric_key = 'metric_type_1')
and (select m_date
from main.metrics between $startDate and $endDate)
)
where rownum = 1
This might work:
select user_id, transaction_id, t_timestamp from (select *, row_number() over (partition by (user_id || '*' || transaction_id) order by f_time asc) rownum
from transactionMetricsView
where metric_1 in (select metric_value
from main.metrics
where metric_key = 'metric_type_1'
and m_date between $startDate and $endDate
)
and rownum = 1