How use Group by and Max(date) multi record - sql

i want Group by by Max(Datetime) each record. but i query have dupplicatate record. i want don't duplicate record.
SQL:
select a.pmn_code,
a.ref_period,
a.SERVICE_TYPE,
min(a.status) keep (dense_rank last order by a.updated_dtm) as status,
max(a.updated_dtm) as updated_dtm
from tempChkStatus a
group by a.pmn_code, a.ref_period, a.SERVICE_TYPE
Data Table tempChkStatus:
PMN_CODE | REF_PERIOD | SERVICE_TYPE | STATUS | UPDATED_DTM
A | 01/2016 | OI | I | 19/08/2016 10:54:44
A | 01/2016 | OP | N | 06/06/2017 15:09:55
A | 02/2016 | OT | I | 31/08/2016 08:37:45
A | 02/2016 | OT | N | 12/10/2016 11:13:56
A | 04/2016 | OI | I | 19/08/2016 10:54:44
A | 04/2016 | OP | N | 06/06/2017 15:09:55
Result SQL:
PMN_CODE | REF_PERIOD | SERVICE_TYPE | STATUS | UPDATED_DTM
A | 01/2016 | OI | I | 19/08/2016 10:54:44
A | 01/2016 | OP | N | 06/06/2017 15:09:55
A | 02/2016 | OT | N | 12/10/2016 11:13:56
A | 04/2016 | OI | I | 19/08/2016 10:54:44
A | 04/2016 | OP | N | 06/06/2017 15:09:55
But I want Result:
PMN_CODE | REF_PERIOD | SERVICE_TYPE | STATUS | UPDATED_DTM
A | 01/2016 | OP | N | 06/06/2017 15:09:55
A | 02/2016 | OT | N | 12/10/2016 11:13:56
A | 04/2016 | OP | N | 06/06/2017 15:09:55
Help me please. Thanks advance ;)

with tempChkStatus (
PMN_CODE, REF_PERIOD , SERVICE_TYPE , STATUS , UPDATED_DTM) as
(
select 'A', '01/2016' ,'OI', 'I', to_date('19/08/2016 10:54:44', 'dd/mm/yyyy hh24:mi:ss') from dual union all
select 'A', '01/2016' ,'OP', 'N', to_date('06/06/2017 15:09:55', 'dd/mm/yyyy hh24:mi:ss') from dual union all
select 'A', '02/2016' ,'OT', 'I', to_date('31/08/2016 08:37:45', 'dd/mm/yyyy hh24:mi:ss') from dual union all
select 'A', '02/2016' ,'OT', 'N', to_date('12/10/2016 11:13:56', 'dd/mm/yyyy hh24:mi:ss') from dual union all
select 'A', '04/2016' ,'OI', 'I', to_date('19/08/2016 10:54:44', 'dd/mm/yyyy hh24:mi:ss') from dual union all
select 'A', '04/2016' ,'OP', 'N', to_date('06/06/2017 15:09:55', 'dd/mm/yyyy hh24:mi:ss') from dual
)
select * from (
select e.*, max(updated_dtm) over (partition by ref_period) md from tempchkstatus e
)
where updated_dtm = md
;

You just need to remove SERVICE_TYPE from the GROUP BY:
select s.pmn_code, s.ref_period,
min(s.SERVICE_TYPE) as service_type,
min(s.status) keep (dense_rank last order by s.updated_dtm) as status,
max(s.updated_dtm) as updated_dtm
from tempChkStatus s
group by s.pmn_code, s.ref_period;
The GROUP BY expressions define the rows returns by an aggregation query.
This version uses MIN() on SERVICE_TYPE. It is not clear what logic you want for the result set.

Related

make recent log agg with unix timestamp in BigQuery

I'm making a webpage user access log table in BigQuery.
But I don't know how agg log with exit_time.
I want recent 5 view page log array.
If view page log is less than 5, the array is shorter.
plz teach me.
USER_EXIT_LOG AS (
SELECT
['A','A','B'] AS user_id,
[1000,2000,1000] AS exit_time
),
VIEW_PAGE_LOG AS (
SELECT
['A','A','A','A','A','B','B'] AS user_id,
['a','b','c','d','e','a','b'] AS view_page_id,
[800,900,1800,1900,1950,800,900] AS time
)
USER_EXIT_LOG
| user_id | exit_time |
| -------- | --------- |
| A | 1000 |
| A | 2000 |
| B | 1000 |
VIEW_PAGE_LOG
| user_id | view_page_id | view_time |
| -------- | ----------- | --------- |
| A | a | 800 |
| A | b | 900 |
| A | c | 1800 |
| A | d | 1900 |
| B | a | 800 |
| B | b | 900 |
WHAT I WANT
| user_id | exit_time | view_page_array |
| ------- | --------- | --------------- |
| A | 1000 | [b,a] |
| A | 2000 | [e,d,c] |
| B | 1000 | [b,a] |
Consider below
select u.user_id, exit_time,
array_agg(view_page_id order by view_time desc limit 5) as view_page_array
from (
select user_id, exit_time,
ifnull(lag(exit_time + 1) over(partition by user_id order by exit_time), 0) start_time
from `project.dataset.USER_EXIT_LOG`
) u
join `project.dataset.VIEW_PAGE_LOG` v
on u.user_id = v.user_id
and view_time between start_time and exit_time
group by user_id, exit_time
If applied t sample data in your question
with `project.dataset.USER_EXIT_LOG` as (
select 'A' user_id, 1000 exit_time union all
select 'A', 2000 union all
select 'B', 1000
), `project.dataset.VIEW_PAGE_LOG` as (
select 'A' user_id, 'a' view_page_id, 800 view_time union all
select 'A', 'b', 900 union all
select 'A', 'c', 1800 union all
select 'A', 'd', 1900 union all
select 'A', 'e', 1950 union all
select 'B', 'a', 800 union all
select 'B', 'b', 900
)
the output is

Monthly Snapshot using Date Dimension

I've some columns that I need to bring to a consolidated table(fact). I've a change capture table which captures changes to record everyday which looks like this:
CHG_TABLE:
+--------+-------------------+-----------------------+-----------+-----------+
| Key | Start_Date | End_Date | Value |Record_Type|
+--------+----- -------------+-----------------------+-----------+-----------+
| 1 | 5/25/2019 2.05 | 12/31/9999 00.00 | 800 | Insert |
| 1 | 5/25/2019 2.05 | 5/31/2019 11.12 | 800 | Update |
| 1 | 5/31/2019 11.12 | 12/31/9999 00.00 | 900 | Insert |
| 1 | 5/31/2019 11.12 | 6/15/2019 12.05 | 900 | Update |
| 1 | 6/15/2019 12.05 | 12/31/9999 00.00 | 1000 | Insert |
| 1 | 6/15/2019 12.05 | 6/25/2019 10.20 | 1000 | Update |
| 1 | 6/25/2019 10.20 | 12/31/9999 00.00 | 500 | Insert |
| 1 | 6/25/2019 10.20 | 6/30/2019 11.12 | 500 | Update |
| 1 | 6/30/2019 11.12 | 12/31/9999 00.00 | 3000 | Insert |
| 1 | 6/30/2019 11.12 | 7/15/2019 1.20 | 3000 | Update |
| 1 | 7/15/2019 1.20 | 12/31/9999 00.00 | 7000 | Insert |
+--------+-------------------+-----------------------+-----------+-----------+
During first insert, End_Date is end of time. When new record with new Start_Date and Value is added to the source it's captured as new entry and previous record with same Key is updated with End_Date as Start_Date of new record.
DIM_DATE:
+--------+-------------------+-----------------------+
|DateKey | Month_Start_Date | Month_End_Date |
+--------+-----+-------------+-----------------------+
| 1 | 6/1/2019 | 6/30/2019 |
| 2 | 7/1/2019 | 7/31/2019 |
+--------+-------------------+-----------------------+
I am struggling since I am using DATE dimension which has Month_Start_Date and Month_End_Date.
I want to create a monthly snapshot from this change table which would look like this:
RESULT:
+--------+-------------------+-----------------------+-----------+-----------+
| Key | Month_Start_Date | Month_End_Date |Begin_Value|End_Value |
+--------+-----+-------------+-----------------------+-----------+-----------+
| 1 | 6/1/2019 | 6/30/2019 | 800 | 500 |
| 1 | 7/1/2019 | 7/31/2019 | 500 | 3000 |
+--------+-------------------+-----------------------+-----------+-----------+
Begin_Value : Max(End_Date) < Month_Start_Date
End_Value : Max(End_Date) <= Month_End_Date
The Begin_Value should be most recent value from last month(which is not end of the time) and End_Value should be the most recent value based on Month_End_Date.
How to show above result?
I think you should rethink your logic a bit.
If CHG_TABLE has a 'update' record on July 15th and there is no later change, then that new value should be end value for July.
Assuming (big if) that's correct, then you should just ignore the END_DATE column altogether. If you're able, drop it from your data model. You don't need it.
Instead, create a descending index on CHG_TABLE.START_DATE, like so:
create index chg_table_n1 on chg_table (start_date desc);
Then, you should be able to create your snapshot fairly efficiently like this:
select ct.key,
dd.month_start_date,
dd.month_end_date,
( SELECT value
FROM chg_table ct2
WHERE ct2.key = ct.key
AND ct2.start_date < dd.month_start_date
ORDER BY ct2.start_date DESC
FETCH FIRST 1 ROW ONLY ) first_value,
max(ct.value) keep ( dense_rank last order by ct.start_date ) last_value
from dim_date dd
INNER JOIN chg_table ct ON ct.start_date BETWEEN dd.month_start_date and dd.month_end_date
GROUP BY ct.key, dd.month_start_date, dd.month_end_date;
Hopefully you are on release 12.1 or later for the FETCH FIRST syntax. Otherwise, you'll need to tweak that part to the pre-12.1 equivalent.
FULL EXAMPLE WITH TEST DATA
WITH chg_table ( key, start_date, end_date, value, record_type ) AS
(
SELECT 1,TO_DATE('5/25/2019 2.05','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'), 800, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('5/25/2019 2.05','MM/DD/YYYY HH24.MI'),TO_DATE('5/31/2019 11.12','MM/DD/YYYY HH24.MI'), 800, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('5/31/2019 11.12','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'), 900, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('5/31/2019 11.12','MM/DD/YYYY HH24.MI'),TO_DATE('6/15/2019 12.05','MM/DD/YYYY HH24.MI'), 900, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/15/2019 12.05','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'), 1000, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/15/2019 12.05','MM/DD/YYYY HH24.MI'),TO_DATE('6/25/2019 10.20','MM/DD/YYYY HH24.MI'), 1000, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/25/2019 10.20','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'), 500, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/25/2019 10.20','MM/DD/YYYY HH24.MI'),TO_DATE('6/30/2019 11.12','MM/DD/YYYY HH24.MI'), 500, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/30/2019 11.12','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'),3000, 'Insert' FROM DUAL UNION ALL
SELECT 1,TO_DATE('6/30/2019 11.12','MM/DD/YYYY HH24.MI'),TO_DATE('7/15/2019 1.20','MM/DD/YYYY HH24.MI'), 3000, 'Update' FROM DUAL UNION ALL
SELECT 1,TO_DATE('7/15/2019 1.20','MM/DD/YYYY HH24.MI'),TO_DATE('12/31/9999 00.00','MM/DD/YYYY HH24.MI'),7000, 'Insert' FROM DUAL ),
dim_date ( datekey, month_start_date, month_end_date ) AS (
SELECT 1, DATE'2019-05-01', DATE'2019-06-01' - INTERVAL '1' SECOND FROM DUAL UNION ALL
SELECT 2, DATE'2019-06-01', DATE'2019-07-01' - INTERVAL '1' SECOND FROM DUAL UNION ALL
SELECT 3, DATE'2019-07-01', DATE'2019-08-01' - INTERVAL '1' SECOND FROM DUAL )
select ct.key,
dd.month_start_date,
dd.month_end_date,
( SELECT value
FROM chg_table ct2
WHERE ct2.key = ct.key
AND ct2.start_date < dd.month_start_date
ORDER BY ct2.start_date DESC
FETCH FIRST 1 ROW ONLY ) first_value,
max(ct.value) keep ( dense_rank last order by ct.start_date ) last_value
from dim_date dd
INNER JOIN chg_table ct ON ct.start_date BETWEEN dd.month_start_date and dd.month_end_date
GROUP BY ct.key, dd.month_start_date, dd.month_end_date;
+-----+------------------+----------------+-------------+------------+
| KEY | MONTH_START_DATE | MONTH_END_DATE | FIRST_VALUE | LAST_VALUE |
+-----+------------------+----------------+-------------+------------+
| 1 | 01-MAY-19 | 31-MAY-19 | | 900 |
| 1 | 01-JUN-19 | 30-JUN-19 | 900 | 3000 |
| 1 | 01-JUL-19 | 31-JUL-19 | 3000 | 7000 |
+-----+------------------+----------------+-------------+------------+
Update - version w/o MAX()..KEEP(), assuming the existence of DIM_PERSON table
select k.key,
dd.month_start_date,
dd.month_end_date,
( SELECT value
FROM chg_table ct2
WHERE ct2.key = k.key
AND ct2.start_date < dd.month_start_date
ORDER BY ct2.start_date DESC
FETCH FIRST 1 ROW ONLY ) first_value,
( SELECT value
FROM chg_table ct2
WHERE ct2.key = k.key
AND ct2.start_date <= dd.month_end_date
ORDER BY ct2.start_date DESC
FETCH FIRST 1 ROW ONLY ) last_value
from dim_date dd
CROSS JOIN dim_person k
GROUP BY k.key, dd.month_start_date, dd.month_end_date;

Oracle normalize multiple rows into new view

I need to find a solution for the following problem.
Out internal postman has to scan a QR-barcode on a mailbox first and a datamatrix-barcode on each (internal) letter he puts into the mailbox.
The data from his scanner-device is stored into a Oracle 11g database-table in the following format
|----|---------------------|--------------|---------------|
| ID | SCAN_DATE | BAROCDE_TYPE | BARCODE_VALUE |
----------------------------------------------------------|
| 1 | 2016/02/01 08:10:30 | QR | Dept_HR |
| 2 | 2016/02/01 08:10:35 | DM | Lett_1 |
| 3 | 2016/02/01 08:10:38 | DM | Lett_3 |
| 4 | 2016/02/01 08:10:41 | DM | Lett_6 |
| 5 | 2016/02/01 08:16:37 | QR | Dept_FI |
| 6 | 2016/02/01 08:16:38 | DM | Lett_2 |
| 7 | 2016/02/01 08:16:40 | DM | Lett_4 |
|----|---------------------|--------------|---------------|
I want to "normalize?" the data into a database-view in the following format
(where it easy to see which letter was delivered to which mailbox)
|---------------------|------------|---------------------|----------|
| ScanDate Postbox | Department | ScanDate Letter | LetterID |
|---------------------|------------|---------------------|----------|
| 2016/02/01 08:10:30 | Dept_HR | 2016/02/01 08:10:35 | Lett_1 |
| 2016/02/01 08:10:30 | Dept_HR | 2016/02/01 08:10:38 | Lett_3 |
| 2016/02/01 08:10:30 | Dept_HR | 2016/02/01 08:10:41 | Lett_6 |
| 2016/02/01 08:16:37 | Dept_FI | 2016/02/01 08:16:38 | Lett_2 |
| 2016/02/01 08:16:37 | Dept_FI | 2016/02/01 08:16:40 | Lett_4 |
|---------------------|------------|---------------------|----------|
Any ideas how I can create an oracle database-view showing the data as described above?
I guess the Postbox record is the previous record to the letter records. This is a bad because unsafe association.
the following select should do the job:
-- Your testdata
with data(id,
scan_date,
barcode_type,
barcode_value) as
(select 1,
to_date('2016/02/01 08:10:30', 'YYYY/MM/DD HH24:MI:SS'),
'QR',
'Dept_HR'
from dual
union all
select 2,
to_date('2016/02/01 08:10:35', 'YYYY/MM/DD HH24:MI:SS'),
'DM',
'Lett_1'
from dual
union all
select 3,
to_date('2016/02/01 08:10:38', 'YYYY/MM/DD HH24:MI:SS'),
'DM',
'Lett_3'
from dual
union all
select 4,
to_date('2016/02/01 08:10:41', 'YYYY/MM/DD HH24:MI:SS'),
'DM',
'Lett_6'
from dual
union all
select 5,
to_date('2016/02/01 08:16:37', 'YYYY/MM/DD HH24:MI:SS'),
'QR',
'Dept_FI'
from dual
union all
select 6,
to_date('2016/02/01 08:16:38', 'YYYY/MM/DD HH24:MI:SS'),
'DM',
'Lett_2'
from dual
union all
select 7,
to_date('2016/02/01 08:16:40', 'YYYY/MM/DD HH24:MI:SS'),
'DM',
'Lett_4'
from dual)
-- Select
select dp.scan_date as "ScanDate Postbox",
dp.barcode_value as "Departement",
d.scan_date as "ScanDate Letter",
d.barcode_value as "LetterId"
from data dp, data d
where d.barcode_type = 'DM'
and dp.barcode_type = 'QR'
and dp.scan_date =
(select max(dpp.scan_date)
from data dpp
where dpp.barcode_type = dp.barcode_type
and dpp.scan_date <= d.scan_date);

Generate the rank/number if the difference between consecutive rows is less than 10 days

Need hive query that calculates the date difference for consecutive records but for the same txn type and generate same number if the difference is less than 10 else generate new number.
Input table
+--------+----------+-------------+
| Txn_id | Txn_type | Txn_date |
+--------+----------+-------------+
| 1 | T100 | 26-Aug-2015 |
| 2 | T100 | 03-Nov-2015 |
| 3 | T100 | 05-Dec-2015 |
| 4 | T100 | 08-Dec-2015 |
| 5 | T100 | 25-Jan-2016 |
| 6 | T111 | 26-Jan-2016 |
| 7 | T200 | 02-Feb-2016 |
| 8 | T200 | 07-May-2016 |
| 9 | T200 | 12-May-2016 |
| 10 | T200 | 20-May-2016 |
+--------+----------+-------------+
Expected output
+--------+----------+-------------+--------+
| Txn_id | Txn_type | Txn_date | Number |
+--------+----------+-------------+--------+
| 1 | T100 | 26-Aug-2015 | 1 |
| 2 | T100 | 03-Nov-2015 | 2 |
| 3 | T100 | 05-Dec-2015 | 3 |
| 4 | T100 | 08-Dec-2015 | 3 |
| 5 | T100 | 25-Jan-2016 | 4 |
| 6 | T111 | 26-Jan-2016 | 1 |
| 7 | T200 | 02-Feb-2016 | 1 |
| 8 | T200 | 07-May-2016 | 2 |
| 9 | T200 | 12-May-2016 | 2 |
| 10 | T200 | 20-May-2016 | 2 |
+--------+----------+-------------+--------+
Not sure if "less than 10 days" means strict or non-strict inequality, but otherwise:
with
inputs ( txn_id, txn_type, txn_date ) as (
select 1, 'T100', to_date('26-Aug-2015', 'dd-Mon-yy') from dual union all
select 2, 'T100', to_date('03-Nov-2015', 'dd-Mon-yy') from dual union all
select 3, 'T100', to_date('05-Dec-2015', 'dd-Mon-yy') from dual union all
select 4, 'T100', to_date('08-Dec-2015', 'dd-Mon-yy') from dual union all
select 5, 'T100', to_date('25-Jan-2016', 'dd-Mon-yy') from dual union all
select 6, 'T111', to_date('26-Jan-2016', 'dd-Mon-yy') from dual union all
select 7, 'T200', to_date('02-Feb-2016', 'dd-Mon-yy') from dual union all
select 8, 'T200', to_date('07-May-2016', 'dd-Mon-yy') from dual union all
select 9, 'T200', to_date('12-May-2016', 'dd-Mon-yy') from dual union all
select 10, 'T200', to_date('20-May-2016', 'dd-Mon-yy') from dual
),
prep ( txn_id, txn_type, txn_date, ct ) as (
select txn_id, txn_type, txn_date,
case when txn_date < lag(txn_date) over (partition by txn_type
order by txn_date) + 10 then 0 else 1 end
from inputs
)
select txn_id, txn_type, txn_date,
sum(ct) over (partition by txn_type order by txn_date) as number_
from prep;
I used number_ as a column name; don't use reserved Oracle words for table or column names unless your life depends on it, and not even then.
Use a common table expression to mark the rows that have a difference of more than 10 days and then count those to get the new number.
with test_data as (
SELECT 1 txn_id, 'T100' txn_type, to_date('26-AUG-2015','DD-MON-YYYY') txn_date from dual union all
SELECT 2 txn_id, 'T100', to_date('03-NOV-2015','DD-MON-YYYY') from dual union all
SELECT 3 txn_id, 'T100', to_date('05-DEC-2015','DD-MON-YYYY') from dual union all
SELECT 4 txn_id, 'T100', to_date('08-DEC-2015','DD-MON-YYYY') from dual union all
SELECT 5 txn_id, 'T100', to_date('25-JAN-2016','DD-MON-YYYY') from dual union all
SELECT 6 txn_id, 'T111', to_date('26-JAN-2016','DD-MON-YYYY') from dual union all
SELECT 7 txn_id, 'T200', to_date('02-FEB-2016','DD-MON-YYYY') from dual union all
SELECT 8 txn_id, 'T200', to_date('07-MAY-2016','DD-MON-YYYY') from dual union all
SELECT 9 txn_id, 'T200', to_date('12-MAY-2016','DD-MON-YYYY') from dual union all
SELECT 10 txn_id, 'T200', to_date('20-MAY-2016','DD-MON-YYYY') from dual),
markers as (
select td.*,
case when td.txn_date - nvl(lag(td.txn_date)
over ( partition by txn_type order by txn_id ), td.txn_date-9999) > 10
THEN 'Y' ELSE NULL end new_txn_marker from test_data td )
SELECT txn_id, txn_type,txn_date,
count(new_txn_marker) over ( partition by txn_type order by txn_id ) "NUMBER"
FROM markers;

Oracle SQL - Listagg with Rtrim and Regexp - Duplicates still present

I am using LISTAGG with RTRIM and REGEXP_REPLACE to create a comma delimited list of Test Scores but remove duplicates.
The problem is that there are still duplicates.
The data given below is directly from the SORTEST table. (SELECT * FROM SORTEST WHERE SORTEST_PIDM = '260670') I did eliminate the columns I am not using.
Q1: Why are there duplicates?
Q2: How can they be eliminated?
I think it may have to do with there being two sets of A01-A05 scores. It only happens on persons with more than one set of A scores. This does not make sense to me though since I am looking for scores LIKE 'A%B'
CODE:
SELECT DISTINCT
SP.SPRIDEN_ID AS "STUDENT_ID",
t2.sortest_pidm,
SP.SPRIDEN_LAST_NAME AS "LAST",
SP.SPRIDEN_FIRST_NAME AS "FIRST",
RTRIM(
REGEXP_REPLACE(
(
listagg ((T2.SORTEST_TESC_CODE || '-' || T2.SORTEST_TEST_SCORE), ', ')
WITHIN GROUP (ORDER BY SP.SPRIDEN_ID)
OVER (PARTITION BY SP.SPRIDEN_ID)),
'([^-]*)(-\1)+($|-)',
'\1\3'),
'-') TEST
FROM
SPRIDEN SP
left outer join SPBPERS B on SP.spriden_pidm = b.spbpers_pidm
JOIN SORTEST T2 ON T2.SORTEST_PIDM = SP.SPRIDEN_PIDM
WHERE
SP.SPRIDEN_CHANGE_IND IS NULL
AND B.SPBPERS_DEAD_IND IS NULL
AND B.SPBPERS_CONFID_IND <> 'Y'
AND T2.SORTEST_TADM_CODE IS NULL
AND
T2.SORTEST_TESC_CODE IN ('CM1B', 'CM2B', 'CR1B', 'CW1B', 'A01B', 'A02B', 'A03B', 'A04B',
'A05B', 'S01B', 'S02B', 'S95B', 'DSPW', 'DSPR', 'DSPM')
AND sP.spriden_change_ind is null
AND SP.SPRIDEN_ID IN ( 'A00154876')
Data
Please note that SORTEST_PIDM = SPRIDEN_PIDM. I did not include the SPRIDEN ID or name because I wanted to simplify the data section.
+--------------+-------------------+-------------------+--------------------+
| SORTEST_PIDM | SORTEST_TESC_CODE | SORTEST_TEST_DATE | SORTEST_TEST_SCORE |
+--------------+-------------------+-------------------+--------------------+
| | | | |
| 260670 | A01 | 1-Mar-12 | 20 |
| 260670 | A01 | 1-Oct-12 | 22 |
| 260670 | A01B | 9-Jan-13 | 22 |
| 260670 | A02 | 1-Mar-12 | 19 |
| 260670 | A02 | 1-Oct-12 | 19 |
| 260670 | A02B | 5-Jun-12 | 19 |
| 260670 | A03 | 1-Mar-12 | 21 |
| 260670 | A03 | 1-Oct-12 | 19 |
| 260670 | A03B | 5-Jun-12 | 21 |
| 260670 | A04 | 1-Mar-12 | 23 |
| 260670 | A04 | 1-Oct-12 | 22 |
| 260670 | A04B | 5-Jun-12 | 23 |
| 260670 | A05 | 1-Mar-12 | 21 |
| 260670 | A05 | 1-Oct-12 | 21 |
| 260670 | A05B | 5-Jun-12 | 21 |
| 260670 | DSPM | 5-Jun-12 | 4 |
| 260670 | DSPR | 5-Jun-12 | 4 |
| 260670 | DSPW | 5-Jun-12 | 4 |
+--------------+-------------------+-------------------+--------------------+
Results:
+------------+--------------+--------+--------+------------------------------------------------+
| STUDENT_ID | SORTEST_PIDM | LAST | FIRST | TEST |
+------------+--------------+--------+--------+------------------------------------------------+
| A00154876 | 260670 | Fowler | Martin | A01B-22, A02B-19, A03B-21, A04B-23, A05B-21, |
| | | | | DSPM-4, DSPR-4, DSPW-4, |
| | | | | A01B-22, A02B-19, A03B-21, A04B-23, A05B-21, |
| | | | | DSPM-4, DSPR-4, DSPW-4 |
+------------+--------------+--------+--------+------------------------------------------------+
These are my Desired Results:
+------------+--------------+--------+--------+--------------------------------------------+
| STUDENT_ID | SORTEST_PIDM | LAST | FIRST | TEST |
+------------+--------------+--------+--------+--------------------------------------------+
| A00249466 | 260670 | Fowler | Martin | A01B-22, A02B-19, A03B-21,A04B-23, A05B-21,|
| | | | | DSPM-4, DSPR-4, DSPW-4 |
+------------+--------------+--------+--------+--------------------------------------------+
Oracle Setup:
CREATE TABLE SPRIDEN( SPRIDEN_ID, SPRIDEN_PIDM, SPRIDEN_LAST_NAME, SPRIDEN_FIRST_NAME ) AS
SELECT 'A00154876', 260670, 'Fowler', 'Martin' FROM DUAL;
CREATE TABLE SORTEST ( SORTEST_PIDM, SORTEST_TESC_CODE, SORTEST_TEST_DATE, SORTEST_TEST_SCORE ) AS
SELECT 260670, 'A01', DATE '2012-03-1', 20 FROM DUAL UNION ALL
SELECT 260670, 'A01', DATE '2012-10-1', 22 FROM DUAL UNION ALL
SELECT 260670, 'A01B', DATE '2013-01-9', 22 FROM DUAL UNION ALL
SELECT 260670, 'A02', DATE '2012-03-1', 19 FROM DUAL UNION ALL
SELECT 260670, 'A02', DATE '2012-10-1', 19 FROM DUAL UNION ALL
SELECT 260670, 'A02B', DATE '2012-06-5', 19 FROM DUAL UNION ALL
SELECT 260670, 'A03', DATE '2012-03-1', 21 FROM DUAL UNION ALL
SELECT 260670, 'A03', DATE '2012-10-1', 19 FROM DUAL UNION ALL
SELECT 260670, 'A03B', DATE '2012-06-5', 21 FROM DUAL UNION ALL
SELECT 260670, 'A04', DATE '2012-03-1', 23 FROM DUAL UNION ALL
SELECT 260670, 'A04', DATE '2012-10-1', 22 FROM DUAL UNION ALL
SELECT 260670, 'A04B', DATE '2012-06-5', 23 FROM DUAL UNION ALL
SELECT 260670, 'A05', DATE '2012-03-1', 21 FROM DUAL UNION ALL
SELECT 260670, 'A05', DATE '2012-10-1', 21 FROM DUAL UNION ALL
SELECT 260670, 'A05B', DATE '2012-06-5', 21 FROM DUAL UNION ALL
SELECT 260670, 'DSPM', DATE '2012-06-5', 4 FROM DUAL UNION ALL
SELECT 260670, 'DSPR', DATE '2012-06-5', 4 FROM DUAL UNION ALL
SELECT 260670, 'DSPW', DATE '2012-06-5', 4 FROM DUAL;
Query:
SELECT DISTINCT
SP.SPRIDEN_ID AS "STUDENT_ID",
t2.sortest_pidm,
SP.SPRIDEN_LAST_NAME AS "LAST",
SP.SPRIDEN_FIRST_NAME AS "FIRST",
listagg ( T2.SORTEST_TESC_CODE || '-' || T2.SORTEST_TEST_SCORE, ', ')
WITHIN GROUP (ORDER BY T2.SORTEST_TESC_CODE, T2.SORTEST_TEST_SCORE)
OVER (PARTITION BY SP.SPRIDEN_ID) AS TEST
FROM SPRIDEN SP
JOIN ( SELECT DISTINCT
SORTEST_PIDM,
SORTEST_TESC_CODE,
SORTEST_TEST_SCORE
FROM SORTEST
WHERE SORTEST_TESC_CODE IN ('CM1B', 'CM2B', 'CR1B', 'CW1B', 'A01B', 'A02B', 'A03B', 'A04B', 'A05B', 'S01B', 'S02B', 'S95B', 'DSPW', 'DSPR', 'DSPM') ) T2
ON T2.SORTEST_PIDM = SP.SPRIDEN_PIDM;
Results:
STUDENT_ID SORTEST_PIDM LAST FIRST TEST
---------- ------------ ------ ------ --------------------------------------------------------------------
A00154876 260670 Fowler Martin A01B-22, A02B-19, A03B-21, A04B-23, A05B-21, DSPM-4, DSPR-4, DSPW-4