Data Wont Return - sql

I have added a timestamp statement to the below SQL but it is not adding it to the table.
with cx(seq, user_id, mod_date_time, menu_optn_name) as (
select 1, 'U1', timestamp '2007-05-21 16:00:00', 'O1' from dual),
cc(seq, user_id, mod_date_time, menu_optn_name) as (
select seq, user_id, cast(mod_date_time as date), menu_optn_name from cx)
select
user_id, MENU_OPTN_NAME, MOD_DATE_TIME,
case
when MOD_DATE_TIME > prior MOD_DATE_TIME+(1/96) and user_id = prior user_id then round((MOD_DATE_TIME - prior MOD_DATE_TIME)*1440,2)
else null
end as TIME_GAP
from
(select
ptt.user_id, MENU_OPTN_NAME, ptt.MOD_DATE_TIME,
row_number() over (partition by ptt.user_id order by ptt.MOD_DATE_TIME) seq
from PROD_TRKG_TRAN ptt
join cd_master cm on
ptt.cd_master_id = cm.cd_master_id
Where
MENU_OPTN_NAME = 'Cycle Cnt {Reserve}' --CHANGE BASED ON WHAT YOUR TRACKING... MENU NAMES AT THE BOTTOM
and ptt.user_id = 'SCOUNCIL' --CHANGE BASED ON WHO YOU WANT TO TRACK FOR A GAP...
and cm.cd_master_id =
(select cd_master_id
from cd_master
where
co = '&CO'
and div = '&DIV')
and ptt.create_date_time >=
/*Today*/ trunc(sysdate)
--/*This Week*/ trunc(sysdate-(to_char(sysdate,'D')-1))
--/*This Month*/ trunc(sysdate)-(to_char(sysdate,'DD')-1)
--/*Date Range*/ '&FromDate' and ptt.create_date_time-1 < '&ToDate'
--group by ptt.user_id
)cc
CONNECT BY
user_id = prior user_id
and seq = prior seq+1
start with
seq = 1
I have the query to show me anything with a time gap greater then 15 will tell me how long the gap is but I want it to account for the start time of the shift being 4PM so if they start work at 4pm and don't do anything in the system until 4:41PM then there was a 41 min gap.
not sure what I did wrong... I built the timestamp part separate and then put it into the query possibly its not meant to go with a query and should be on its own.
Thanks for any insight with this issue.

Related

Find increase in history records in specific range

I want to find records in date range 1/1/19-1/7/19 which increase amount
using table HISTORY:
DATE AMOUNT ID
(Date, number, varchar2(30))
I find IDs inside range correctly
assuming increase/decrease can happens only when having two records with same Id
with suspect as
(select id
from history
where t.createddate < to_date('2019-07-01', 'yyyy-mm-dd')
group by id
having count(1) > 1),
ids as
(select id
from history
join suspect
on history.id = suspect.id
where history.date > to_date('2019-01-01', 'yyyy-mm-dd')
and history.date < to_date('2019-07-01', 'yyyy-mm-dd'))
select count(distinct id)
from history a, history b
where a.id = b.id
and a.date < b.date
and a.amount < b.amount
The problem to find increase I need to find previous record which can be before time range
I can find last previous time before time range, but I failed to use it:
ids_prevtime as (
select history.*, max(t.date) over (partition by t.id) max_date
from history
join ids on history.userid = ids.id
where history.date < to_date('2019-01-01','yyyy-mm-dd' )
), ids_prev as (
select * from ids_prevtime where createdate=max_date
)
I see that you found solution, but maybe you could do it simpler, using lag():
select count(distinct id)
from (select id, date_, amount,
lag(amount) over (partition by id order by date_) prev_amt
from history)
where date_ between date '2019-01-01' and date '2019-07-01'
and amount > prev_amt;
dbfiddle
Add union of last history records before range with records inside range
ids_prev as
(select ID, DATE, AMOUNT
from id_before_rangetime
where createddate = max_date),
ids_in_range as
(select history.*
from history
join ids
on history.ID = ids.ID
where history.date > to_date('2019-01-01', 'yyyy-mm-dd')
and history.date < to_date('2019-07-01', 'yyyy-mm-dd')),
all_relevant as
(select * from ids_in_range union all select * from ids_prev)
and then count increases:
select count(distinct id)
from all_relevant a, all_relevant b
where a.id = b.id
and a.date < b.date
and a.amount < b.amount

CASE WHEN expression in oracle

I have built a CASE WHEN expression to show me when someone has no system transaction in the system under their user id for anything greater then 15 minutes.
case
when MOD_DATE_TIME > prior MOD_DATE_TIME+(1/96)
and user_id = prior user_id
then round((MOD_DATE_TIME - prior MOD_DATE_TIME)*1440,2)
else null
end as TIME_GAP
That above is the case when statement only. The full query is below:
select
user_id, MENU_OPTN_NAME, MOD_DATE_TIME,
case
when MOD_DATE_TIME > prior MOD_DATE_TIME+(1/96) and user_id = prior user_id then round((MOD_DATE_TIME - prior MOD_DATE_TIME)*1440,2)
else null
end as TIME_GAP
from
(select
ptt.user_id, MENU_OPTN_NAME, ptt.MOD_DATE_TIME,
row_number() over (partition by ptt.user_id order by ptt.MOD_DATE_TIME) seq
from PROD_TRKG_TRAN ptt
join cd_master cm on
ptt.cd_master_id = cm.cd_master_id
Where
MENU_OPTN_NAME = 'Cycle Cnt {Reserve}' --CHANGE BASED ON WHAT YOUR TRACKING... MENU NAMES AT THE BOTTOM
and ptt.user_id = 'LLEE1' --CHANGE BASED ON WHO YOU WANT TO TRACK FOR A GAP...
and cm.cd_master_id =
(select cd_master_id
from cd_master
where
co = '&CO'
and div = '&DIV')
and ptt.create_date_time >=
/*Today*/ trunc(sysdate)
--/*This Week*/ trunc(sysdate-(to_char(sysdate,'D')-1))
--/*This Month*/ trunc(sysdate)-(to_char(sysdate,'DD')-1)
--/*Date Range*/ '&FromDate' and ptt.create_date_time-1 < '&ToDate'
--group by ptt.user_id
)cc
CONNECT BY
user_id = prior user_id
and seq = prior seq+1
start with
seq = 1
What I want the query to do is in the CASE WHEN clause. I want it to account for the shift start time being 4pm, so if they don't do anything till 4:41PM then I would see that listed as a 41 min gap.

How to use a union to show rolled up values

I am using DB2 Syntax and hoping to use a UNION to create an additional row to show the rolled up values.
Rather than doing that the first portion of the union is merely naming the columns, whereas the data from the second union appears.
Here is the first portion
SELECT 'DRIVER ID' AS DRIVER_ID, 'NAME' AS NAME, 'PUNIT' AS PUNIT, 'PHONE' AS PHONE, 1767 AS TERMINAL_NUMBER, 'DRIVER TYPE' AS DRIVER_TYPE,
COALESCE((SELECT ROUND(DEC(SUM(CASE WHEN UPDATED_BY IN ('VISTAR','TM4WIN') THEN 1.00 ELSE 0.00 END))/COUNT(UPDATED_BY),2) FROM ODRSTAT, TLORDER L, DRIVER D WHERE DETAIL_LINE_ID = ORDER_ID AND STATUS_CODE IN ('ARRV#SHIP', 'ARRV#CONS', 'DEPT#SHIP', 'DEPT#CONS')
AND CURRENT_STATUS IN ('EDIBILLED','BILLD') AND L.PICK_UP_DRIVER = D.DRIVER_ID AND
D.TERMINAL_NUMBER IN (SELECT UNIQUE FIRST_FIELD_INSERT FROM SITE WHERE FAX_PHONE_NUMBER = :DIVISION) AND BILL_DATE BETWEEN CURRENT DATE - 1 MONTH AND CURRENT DATE AND ACTUAL_DELIVERY > ACTUAL_PICKUP +30 SECONDS),0) AVG_STATUS_UPDATE,
ROUND(((SELECT MAX(ODOMETER)-MIN(ODOMETER) FROM ODOHIST O
WHERE READINGDATE >= CURRENT DATE - 30 DAYS AND O.UNIT_ID IN (SELECT UNIT_ID FROM PUNIT WHERE ACTIVE_WHERE = 'D' AND FLEET_ID IN (SELECT UNIQUE USER5 FROM SITE WHERE FAX_PHONE_NUMBER = :DIVISION)))
/(SELECT NULLIF(SUM(T2.VOL_PFUEL),0) FROM FC_POS T2 INNER JOIN DRIVER D ON T2.DRIVER_ID = D.DRIVER_ID
WHERE D.TERMINAL_NUMBER IN (SELECT UNIQUE FIRST_FIELD_INSERT FROM SITE WHERE FAX_PHONE_NUMBER = :DIVISION) AND POS_DATE >= CURRENT DATE - 30 DAYS)),2) AVG_MPG,
(SELECT ROUND(AVG(TIMES),2) FROM (SELECT DELIVERY_DRIVER, ROUND(AVG(DEC((DAYS(CHECKIN_DATE) - DAYS(ACTUAL_DELIVERY)) *24 + (HOUR(CHECKIN_DATE) - HOUR(ACTUAL_DELIVERY)))/24),2) TIMES
FROM LIST_CHECKIN_AUDIT, LYNX.TLORDER WHERE LYNX.TLORDER.BILL_NUMBER = LIST_CHECKIN_AUDIT.BILL_NUMBER AND BILL_DATE >= CURRENT TIMESTAMP - 1 MONTH
AND LYNX.TLORDER.DOCUMENT_TYPE = 'INVOICE' AND ACTUAL_DELIVERY < CHECKIN_DATE AND ACTUAL_DELIVERY BETWEEN CURRENT TIMESTAMP - 6 MONTHS AND CURRENT TIMESTAMP + 3 DAYS
GROUP BY LYNX.TLORDER.BILL_NUMBER, DELIVERY_DRIVER) AVERAGES WHERE AVERAGES.DELIVERY_DRIVER IN (SELECT DRIVER_ID FROM DRIVER WHERE ACTIVE_IN_DISP = 'True' AND TERMINAL_NUMBER IN (SELECT UNIQUE FIRST_FIELD_INSERT FROM SITE WHERE FAX_PHONE_NUMBER = :DIVISION))) AS AVG_DAYS_TO_SCAN,
CAST(SUM(CASE WHEN VARCHAR(COALESCE((SELECT DATA FROM CUSTOM_DATA WHERE SRC_TABLE_KEY = DRIVER_ID AND CUSTDEF_ID = '50'),'False' ),10) = 'True' THEN 1 ELSE 0 END) AS VARCHAR(10)) AS DRIVE_AXLE,
(SELECT COUNT(UNIQUE A.BILL_NUMBER) FROM LIST_CHECKIN_AUDIT A INNER JOIN TLORDER T ON T.BILL_NUMBER = A.BILL_NUMBER
WHERE CURRENT_STATUS IN ('EDIBILLED','BILLD') AND COALESCE(PICK_UP_DRIVER,DELIVERY_DRIVER) IN (SELECT DRIVER_ID FROM DRIVER WHERE ACTIVE_IN_DISP = 'True'
AND TERMINAL_NUMBER IN (SELECT UNIQUE FIRST_FIELD_INSERT FROM SITE WHERE FAX_PHONE_NUMBER = :DIVISION)) AND BILL_DATE >= CURRENT DATE - 1 MONTH AND A.DOCUMENT_TYPE = 'DABL') AS DRIVERAXLE_SUBMISSIONS
FROM DRIVER WHERE ACTIVE_IN_DISP = 'True'
AND TERMINAL_NUMBER IN (SELECT UNIQUE FIRST_FIELD_INSERT FROM SITE WHERE FAX_PHONE_NUMBER = :DIVISION)
UNION ALL
SELECT DRIVER_ID, NAME, DEFAULT_PUNIT AS PUNIT, VARCHAR(USER9,12) AS PHONE, TERMINAL_NUMBER, DRIVER_TYPE,
COALESCE((SELECT ROUND(DEC(SUM(CASE WHEN UPDATED_BY IN ('VISTAR','TM4WIN') THEN 1.00 ELSE 0.00 END))/COUNT(UPDATED_BY),2) FROM ODRSTAT, TLORDER L WHERE DETAIL_LINE_ID = ORDER_ID AND STATUS_CODE IN ('ARRV#SHIP', 'ARRV#CONS', 'DEPT#SHIP', 'DEPT#CONS')
AND CURRENT_STATUS IN ('EDIBILLED','BILLD') AND L.PICK_UP_DRIVER = DRIVER_ID AND BILL_DATE BETWEEN CURRENT DATE - 1 MONTH AND CURRENT DATE AND ACTUAL_DELIVERY > ACTUAL_PICKUP +30 SECONDS),0) AS STATUS_UPDATE_PERCENT,
ROUND(((SELECT MAX(ODOMETER)-MIN(ODOMETER) FROM ODOHIST O
WHERE READINGDATE >= CURRENT DATE - 30 DAYS AND O.UNIT_ID = DEFAULT_PUNIT)/(SELECT NULLIF(SUM(T2.VOL_PFUEL),0) FROM FC_POS T2 WHERE T2.DRIVER_ID = DRIVER.DRIVER_ID AND POS_DATE >= CURRENT DATE - 30 DAYS)),2) AS MPG_30DAYS,
(SELECT ROUND(AVG(TIMES),2) FROM (SELECT DELIVERY_DRIVER, ROUND(AVG(DEC((DAYS(CHECKIN_DATE) - DAYS(ACTUAL_DELIVERY)) *24 + (HOUR(CHECKIN_DATE) - HOUR(ACTUAL_DELIVERY)))/24),2) TIMES
FROM LIST_CHECKIN_AUDIT, LYNX.TLORDER WHERE LYNX.TLORDER.BILL_NUMBER = LIST_CHECKIN_AUDIT.BILL_NUMBER AND BILL_DATE >= CURRENT TIMESTAMP - 1 MONTH
AND LYNX.TLORDER.DOCUMENT_TYPE = 'INVOICE' AND ACTUAL_DELIVERY < CHECKIN_DATE AND ACTUAL_DELIVERY BETWEEN CURRENT TIMESTAMP - 6 MONTHS AND CURRENT TIMESTAMP + 3 DAYS
GROUP BY LYNX.TLORDER.BILL_NUMBER, DELIVERY_DRIVER) AVERAGES WHERE AVERAGES.DELIVERY_DRIVER = DRIVER.DRIVER_ID)
AVG_DAYS_TO_SCAN,
VARCHAR(COALESCE((SELECT DATA FROM CUSTOM_DATA WHERE SRC_TABLE_KEY = DRIVER_ID AND CUSTDEF_ID = '50'),'False' ),10) AS DRIVEAXLE,
(SELECT COUNT(UNIQUE A.BILL_NUMBER) FROM LIST_CHECKIN_AUDIT A INNER JOIN TLORDER T ON T.BILL_NUMBER = A.BILL_NUMBER
WHERE CURRENT_STATUS IN ('EDIBILLED','BILLD') AND COALESCE(PICK_UP_DRIVER,DELIVERY_DRIVER) = DRIVER_ID AND BILL_DATE >= CURRENT DATE - 1 MONTH AND A.DOCUMENT_TYPE = 'DABL') AS DRIVERAXLE_SUBMISSIONS_1_MONTH
FROM DRIVER WHERE ACTIVE_IN_DISP = 'True'
AND TERMINAL_NUMBER IN (SELECT UNIQUE FIRST_FIELD_INSERT FROM SITE WHERE FAX_PHONE_NUMBER = :DIVISION)
I've not looked at your code...given the lack of formatting, it's not easy to follow.
However, when I've used UNION in the past to provide rolled up values, I've included extra columns that provides a way for me to differentiate between details and totals. These extra columns is also used as the first column to ORDER BY
Example:
select
digits(HCUSNR) as Cust_Num,
CCUSNM,
char(HINVNR),
hinamt,
-- Control fields
' ' concat digits(HCMPCL),
case
when HTRCDE in ('A', 'E', 'R')
then ' LVL3'
else ' LVL1'
end,
HCUSNR, DDVDSC, HDIVSN
UNION ALL
select
' ',
'Daily Invoice Total',
' ',
sum(hinamt),
-- Control Fields
' ' concat digits(HCMPCL), ' LVL2', 0, ' ', HDIVSN
group by
HDIVSN, HCMPCL
--Following order by applies to entire results set
order by 5,6,7,8,9
But the above was written close to 20 years ago...
If I needed to do it today, I'd use the grouping sets, rollup, and cube functionality that IBM has added to the DB.
What platform and version of DB2 are you using? Are grouping sets, rollup and/or cube an option?

What's the proper SQL query to find a 'status change' before given date?

I have a table of logged 'status changes'. I need to find the latest status change for a user, and if it was a) a certain 'type' of status change (s.new_status_id), and b) greater than 7 days old (s.change_date), then include it in the results. My current query sometimes returns the second-to-latest status change for a given user, which I don't want -- I only want to evaluate the last one.
How can I modify this query so that it will only include a record if it is the most recent status change for that user?
Query
SELECT DISTINCT ON (s.applicant_id) s.applicant_id, a.full_name, a.email_address, u.first_name, s.new_status_id, s.change_date, a.applied_class
FROM automated_responses_statuschangelogs s
INNER JOIN application_app a on (a.id = s.applicant_id)
INNER JOIN accounts_siuser u on (s.person_who_modified_id = u.id)
WHERE now() - s.change_date > interval '7' day
AND s.new_status_id IN
(SELECT current_status
FROM application_status
WHERE status_phase_id = 'In The Flow'
)
ORDER BY s.applicant_id, s.change_date DESC, s.new_status_id, s.person_who_modified_id;
You can use row_number() to filter one entry per applicant:
select *
from (
select row_number() over (partition by applicant_id
order by change_date desc) rn
, *
from automated_responses_statuschangelogs
) as lc
join application_app a
on a.id = lc.applicant_id
join accounts_siuser u
on lc.person_who_modified_id = u.id
join application_status stat
on lc.new_status_id = stat.current_status
where lc.rn = 1
and stat.status_phase_id = 'In The Flow'
and lc.change_date < now() - interval '7' day

How to determine if two records are 1 year apart (using a timestamp)

I need to analyze some weblogs and determine if a user has visited once, taken a year break, and visited again. I want to add a flag to every row (Y/N) with a VisitId that meets the above criteria.
How would I go about creating this sql?
Here are the fields I have, that I think need to be used (by analyzing the timestamp of the first page of each visit):
VisitID - each visit has a unique Id (ie. 12356, 12345, 16459)
UserID - each user has one Id (ie. steve = 1, ted = 2, mark = 12345, etc...)
TimeStamp - looks like this: 2010-01-01 00:32:30.000
select VisitID, UserID, TimeStamp from page_view_t where pageNum = 1;
thanks - any help would be greatly appreciated.
You could rank every user's rows, then join the ranked row set to itself to compare adjacent rows:
;
WITH ranked AS (
SELECT
*,
rnk = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY TimeStamp)
FROM page_view_t
),
flagged AS (
SELECT
*,
IsReturnVisit = CASE
WHEN EXISTS (
SELECT *
FROM ranked
WHERE UserID = r.UserID
AND rnk = r.rnk - 1
AND TimeStamp <= DATEADD(YEAR, -1, r.TimeStamp)
)
THEN 'Y'
ELSE 'N'
END
FROM ranked r
)
SELECT
VisitID,
UserID,
TimeStamp,
IsReturnVisit
FROM flagged
Note: the above flags only return visits.
UPDATE
To flag the first visits same as return visits, the flagged CTE could be modified as follows:
…
SELECT
*,
IsFirstOrReturnVisit = CASE
WHEN p.UserID IS NULL OR r.TimeStamp >= DATEADD(YEAR, 1, p.TimeStamp)
THEN 'Y'
ELSE 'N'
END
FROM ranked r
LEFT JOIN ranked p ON r.UserID = p.UserID AND r.rnk = p.rnk + 1
…
References that might be useful:
WITH common_table_expression (Transact-SQL)
Ranking Functions (Transact-SQL)
ROW_NUMBER (Transact-SQL)
The other guy was faster but since I took time to do it and it's a completely different approach I might as well post It :D.
SELECT pv2.VisitID,
pv2.UserID,
pv2.TimeStamp,
CASE WHEN pv1.VisitID IS NOT NULL
AND pv3.VisitID IS NULL
THEN 'YES' ELSE 'NO' END AS IsReturnVisit
FROM page_view_t pv2
LEFT JOIN page_view_t pv1 ON pv1.UserID = pv2.UserID
AND pv1.VisitID <> pv2.VisitID
AND (pv1.TimeStamp <= DATEADD(YEAR, -1, pv2.TimeStamp)
OR pv2.TimeStamp <= DATEADD(YEAR, -1, pv1.TimeStamp))
AND pv1.pageNum = 1
LEFT JOIN page_view_t pv3 ON pv1.UserID = pv3.UserID
AND (pv3.TimeStamp BETWEEN pv1.TimeStamp AND pv2.TimeStamp
OR pv3.TimeStamp BETWEEN pv2.TimeStamp AND pv1.TimeStamp)
AND pv3.pageNum = 1
WHERE pv2.pageNum = 1
Assuming page_view_t table stores UserID and TimeStamp details of each visit of the user, the following query will return users who have visited taking a break of at least an year (365 days) between two consecutive visits.
select t1.UserID
from page_view_t t1
where (
select datediff(day, max(t2.[TimeStamp]), t1.[TimeStamp])
from page_view_t t2
where t2.UserID = t1.UserID and t2.[TimeStamp] < t1.[TimeStamp]
group by t2.UserID
) >= 365