Yii2 over partition to activerecord - activerecord

SELECT
mksg_id,
valid_from,
price
FROM (SELECT
prices.*
, MAX(valid_from) OVER (PARTITION BY mksg_id) max_date
FROM prices) s
WHERE valid_from = max_date
How can I turn that to ActiveRecord? Thank you.

Related

how can eliminate value in oracle with latest record

i will get latest record by timestamp but it is not filter desired
output
here is code i was try to get latest record bu it is not work me.i will attach a image for better understanding.can you figure out that problems
select *
from (select
id,NPCI_REFMSGID,TO_CHAR (created_date, 'dd.mm.rrrr hh24:mi:ss.ff3')AS created_Date,
rank() over (partition by ID order by TO_CHAR (created_date, 'dd.mm.rrrr hh24:mi:ss.ff3') desc) r
from emnd_tblemandate_mst
--where end_enrollment_date is null
)
where r = 1 AND NPCI_REFMSGID='1ea345bc63644b53a88076040ef979e3'
You are partitioning by ID so you get all rows in your result.
Think it should be
select *
from (select id
, NPCI_REFMSGID
, TO_CHAR (created_date, 'dd.mm.rrrr hh24:mi:ss.ff3')AS created_Date
, rank() over (partition by NPCI_REFMSGID order by created_date desc) r
from emnd_tblemandate_mst
)
where r = 1
AND NPCI_REFMSGID = '1ea345bc63644b53a88076040ef979e3'
Then you get only the newest record for a specific NPCI_REFMSGID

SQL query initial and final balance as well sum of events

I have a fairly big table (about 300gb) as:
event_day event_hour customer_id initial_bal final_bal topups debts
01/01 00 11111 0 50 60 10
01/01 01 11111 50 80 45 15
01/01 02 11111 80 30 0 50
...
I want to summarize it into whole days, e.g.:
event_day customer_id initial_bal final_bal topups debts
01/01 11111 0 30 105 75
...
But I´m having troubles with the analitical functions.. I'm working with something like:
select *
from
(
select
event_day, customer_id, initial_bal, final_bal,
sum(topups) over (partition by event_day, customer_id by event_day, customer_id asc) topups,
row_number() over (partition by event_day, customer_id order by event_day, customer_id asc) as initial_bal,
row_number() over (partition by event_day, customer_id order by event_day, customer_id desc) as final_bal
from MY_300GB_TABLE t
)
where initial_bal = 1 or final_bal = 1
order by customer_id, event_day
Which inst doing what I expected... a hand?
I´m tring to avoid joins, sub-queries and such.. I simplified here but there the actual project involves a few big tables and performance might an issue. I'm using Oracle 12C.
thanks!
Good occasion to aggregate with first (or last) option:
select event_day, customer_id,
max(initial_bal) keep (dense_rank first order by event_hour) initial_bal,
max(final_bal) keep (dense_rank last order by event_hour) final_bal,
sum(topups) topups, sum(debts) debts
from tla_t_balance_summary t
group by event_day, customer_id;
dbfiddle demo
Your query works too, but you made a mistake in order by. And it requires additional aggregation, because we have two rows for customers:
select event_day, customer_id, max(topups), max(debts),
min(case rib when 1 then initial_bal end) ib, min(case rfb when 1 then final_bal end) fb
from (
select event_day, customer_id, initial_bal, final_bal,
sum(topups) over (partition by event_day, customer_id) topups,
sum(debts) over (partition by event_day, customer_id) debts,
row_number() over (partition by event_day, customer_id order by event_hour) as rib,
row_number() over (partition by event_day, customer_id order by event_hour desc) as rfb
from tla_t_balance_summary t)
where rib = 1 or rfb = 1
group by customer_id, event_day;
If you are looking for the first and last entry for each day based on hour, your row_number function should reflect that, with something like:
select *
from
(
select
event_day, customer_id, initial_bal, final_bal,
sum(recharge_amount) over (partition byevent_day, customer_id) topups,
row_number() over (partition by event_day, customer_id order by event_hour asc) as initial_hr,
row_number() over (partition by event_day, customer_id order by event_hour desc) as final_hr
from TLA_T_BALANCE_SUMMARY t
)
where initial_hr = 1 or final_hr = 1
order by customer_id, event_day
Its hard to comment exactly because your query doesn't really match the data in terms of columns etc.
I think you will need to use GROUP BY and analytical function as following:
SELECT
EVENT_DAY,
CUSTOMER_ID,
MAX(INITIAL_BAL) AS INITIAL_BAL,
MAX(FINAL_BAL) AS FINAL_BAL,
SUM(TOPUPS) AS TOPUPS,
SUM(DEBTS) AS DEBTS
FROM
(
SELECT
EVENT_DAY,
CUSTOMER_ID,
FIRST_VALUE(INITIAL_BAL) OVER(
PARTITION BY EVENT_DAY, CUSTOMER_ID
ORDER BY
EVENT_HOUR
) AS INITIAL_BAL,
FIRST_VALUE(FINAL_BAL) OVER(
PARTITION BY EVENT_DAY, CUSTOMER_ID
ORDER BY
EVENT_HOUR DESC
) AS FINAL_BAL,
TOPUPS,
DEBTS
FROM
TLA_T_BALANCE_SUMMARY T
WHERE
INITIAL_BAL = 1
OR FINAL_BAL = 1
)
GROUP BY
EVENT_DAY,
CUSTOMER_ID
ORDER BY
CUSTOMER_ID,
EVENT_DAY;
Cheers!!

Recursive hierarchical Oracle SQL query

I have a source table like below:
Emp_ID| Name| Manager_ID
001|abc|005
005|cde|010
010|xyz|050
050 | bcg| 100
100|sta|NULL
My requirement is to populate the target table like below:
Emp_ID| Name| Manager_1| Manager_2| Manager_3| Manager_4
005|cde|xyz|bcg|sta|NULL
050|bcg|sta| NULL|NULL|NULL
100|sta|NULL|NULL|NULL
001|abc|cde|xyz|bcg|sta
I am able to use recursive select through Connect by clause and populate the value for Manager_1 but not able to get through the logic to populate Manager_2, Manager_3 , Manager_4 values as different column values in a single row depending on how many level of hierarchy is present for a certain employee.
Please help.
I think the following query will help you. But to split the string to individual manager id, you need to know the max no of level of managers.
WITH data_set AS
(SELECT '001' emp_id, 'aaa' emp_name, '005' mgr_id
FROM DUAL
UNION
SELECT '005' emp_id, 'bbb' emp_name, '010' mgr_id
FROM DUAL
UNION
SELECT '010' emp_id, 'ccc' emp_name, '050' mgr_id
FROM DUAL
UNION
SELECT '020' emp_id, 'ddd' emp_name, '050' mgr_id
FROM DUAL
UNION
SELECT '050' emp_id, 'eee' emp_name, '100' mgr_id
FROM DUAL
UNION
SELECT '100' emp_id, 'fff' emp_name, '200' mgr_id
FROM DUAL
UNION
SELECT '200' emp_id, 'ggg' emp_name, NULL mgr_id
FROM DUAL)
SELECT emp_id, emp_name, mgr_id,
LTRIM (SYS_CONNECT_BY_PATH (emp_id, '-'), '-') chain
FROM data_set
START WITH mgr_id IS NULL
CONNECT BY mgr_id = PRIOR emp_id
ORDER SIBLINGS BY emp_id;
If your hierarchy only extends to 4 levels deep, the following query may be used:
select t1.Emp_ID,
t1.Name,
t2.Name as Manager_1,
t3.Name as Manager_2,
t4.Name as Manager_3,
t5.Name as Manager_4
from tmp t1
left join tmp t2 on t2.Emp_ID = t1.Manager_ID
left join tmp t3 on t3.Emp_ID = t2.Manager_ID
left join tmp t4 on t4.Emp_ID = t3.Manager_ID
left join tmp t5 on t5.Emp_ID = t4.Manager_ID;
Pivot option:
SELECT * FROM
(
SELECT emp_id, name, manager_id
FROM employees
)
PIVOT
(
COUNT(manager_id)
FOR manager_id IN ('005', '100', '050')
)
ORDER BY emp_id;

Group by and bring back value in first row

I have query
SELECT ID, TIME, PRICE, QTY
FROM myTable
that returns:
ID TIME PRICE QTY
1295179228 1/29/2015 20:59:37 15.24 1112
1295179228 1/29/2015 20:59:37 15.23 2
1295179228 1/29/2015 20:59:38 15.28 22
1295179228 1/29/2015 20:59:38 15.27 1800
I am then using group by to return the min time, average price and sum of qty BUT I also want to return the first time
SELECT ID, t2.name, min(TIME) as MinTIME, avg(PRICE) as AVGPrice, sum( QTY) as SUMQTY
FROM myTable t inner join table2 t2 on t.id = t2.id
group by ID, t2.name
But how do I add a column in that group by query above that will also return the first PRICE. In that case that would be 15.24
I have been googling and I see oracle has FIRST() and FIRST_VALUE() functions but I could not get them to work.
Thank you.
Assuming that "first price" means "price with the earliest time"
min(price) keep (dense_rank first order by time)
WITH CTE AS
(SELECT ID,"TIME",PRICE,QTY,ROW_NUMBER() OVER (PARTITION BY id ORDER BY TIME ASC) as rn
FROM t)
SELECT ID, min("TIME") as MinTIME, avg(PRICE) as AVGPrice, sum( QTY) as SUMQTY,
MAX(CASE WHEN rn=1 THEN PRICE ELSE 0 END) as FirstPrice
FROM CTE
group by ID

Oracle select most recent date record

I am trying to find the most recent record based on a date field. When I set latest = 1 in the where clause, I get an error. Please help if possible. DATE is a the field I'm sorting by. I have tried both latest = 1 and latest = '1'
SELECT
STAFF_ID,
SITE_ID,
PAY_LEVEL,
ROW_NUMBER() OVER (PARTITION BY STAFF_ID ORDER BY DATE DESC) latest
FROM OWNER.TABLE
WHERE END_ENROLLMENT_DATE is null
AND latest = 1
you can't use aliases from select list inside the WHERE clause (because of the Order of Evaluation of a SELECT statement)
also you cannot use OVER clause inside WHERE clause - "You can specify analytic functions with this clause in the select list or ORDER BY clause." (citation from docs.oracle.com)
select *
from (select
staff_id, site_id, pay_level, date,
max(date) over (partition by staff_id) max_date
from owner.table
where end_enrollment_date is null
)
where date = max_date
Assuming staff_id + date form a uk, this is another method:
SELECT STAFF_ID, SITE_ID, PAY_LEVEL
FROM TABLE t
WHERE END_ENROLLMENT_DATE is null
AND DATE = (SELECT MAX(DATE)
FROM TABLE
WHERE staff_id = t.staff_id
AND DATE <= SYSDATE)
i think i'd try with MAX something like this:
SELECT staff_id, max( date ) from owner.table group by staff_id
then link in your other columns:
select staff_id, site_id, pay_level, latest
from owner.table,
( SELECT staff_id, max( date ) latest from owner.table group by staff_id ) m
where m.staff_id = staff_id
and m.latest = date
select *
from (select
staff_id, site_id, pay_level, date,
rank() over (partition by staff_id order by date desc) r
from owner.table
where end_enrollment_date is null
)
where r = 1

Resources