Count of Consecutive days absent excluding weekends in vertica - vertica

I have a table with attendancedata having date, empno timein/timeout columns without weekend dates(Friday and saturday are weekends) in Vertica
Please Note:
1, The table is DateTimeAttendance
2, Time-In is NULL for those employees who are absent.
So my condition here is
TimeIn=Null
I tried the following analytics features of Vertica on data and got the outpout as follows
select name, date, CONDITIONAL_TRUE_EVENT(date - lag(date)>1) over (partition by name order by date) as ConsecutiveDatesCounter
from DateTimeAttendance
where timein is null group by name,date ;
sample ouput :
name date ConsecutiveDatesCounter
Aaron Gadsen 19/3/2014 0
Aaron Gadsen 23/3/2014 1
Aaron Gadsen 24/3/2014 1
Aaron Gadsen 25/3/2014 1
Aaron Gadsen 26/3/2014 1
Aaron Gadsen 27/3/2014 1
Aaron Gadsen 30/3/2014 2
Aaron Gadsen 31/3/2014 2
Here 28/3/2014 and 29/3/2014 are weekends, so i want the ConsecutiveDatesCounter 1 should not changed to 2, it should remain as 1
I want to get the output as follows
name date ConsecutiveDatesCounter
Aaron Gadsen 19/3/2014 0
Aaron Gadsen 23/3/2014 1
Aaron Gadsen 24/3/2014 1
Aaron Gadsen 25/3/2014 1
Aaron Gadsen 26/3/2014 1
Aaron Gadsen 27/3/2014 1
Aaron Gadsen 30/3/2014 1
Aaron Gadsen 31/3/2014 1
Next query on the above result will be as follows
select name, count(1) num_days, min(date) startdate, max(date) enddate
from (select name, date, CONDITIONAL_TRUE_EVENT(date - lag(date)>1) over (partition by name order by date) as ConsecutiveDatesCounter
from DateTimeAttendance where timein is null group by name,date ) as consecutive
group by name, consecutiveDatesCounter order by startdate;
Final Output should be like this :
name num_days startdate enddate
Aaron Gadsen 1 19/3/2014 19/3/2014
Aaron Gadsen 7 23/3/2014 31/3/2014
Please help me to resolve this issue of weekend in this scenario..
Thanks in Advance

It looks like you really just need to take into account the Friday to Monday. I'm assuming based on your data set that you don't have weekend rows at all (and if you do, you'll want to filter them for this to work). Making the event false for that Monday/Friday scenario (while making sure it is only a 3-day gap). It isn't pretty, maybe someone else has a better way.
CONDITIONAL_TRUE_EVENT( (date - lag(date) > 1) AND NOT ( date - lag(date) = 3 AND DAYOFWEEK(date) = 2 AND DAYOFWEEK(lag(date)) = 6 )

Related

Oracle: Retrieving specific group of records based by date

I have a table in oracle that I'm trying to write a query for but having a problem writing it correctly. The data of the table looks like this:
Name
ID
DATE
Shane
1
01JAN2023
Angie
2
02JAN2023
Shane
1
02JAN2023
Austin
3
03JAN2023
Shane
1
03JAN2023
Angie
2
03JAN2023
Tony
4
05JAN2023
What I was trying to come up with was a way to iterate over each day, look at all the records for that day and compare with the rest of the records in the table that came before it and only pull back the first instance of the record based on the ID & Date. The expected output would be:
Name
ID
DATE
Shane
1
01JAN2023
Angie
2
02JAN2023
Austin
3
03JAN2023
Tony
4
05JAN2023
Can anyone tell me what the query should be to accomplish this?
Thank you in advance.
You'll need to convert your date field to a real date so it orders correctly
SELECT name,id,MIN(TO_DATE(date,'DDMONYYYY')) date
FROM table
GROUP BY name,id
Isn't that just
select name, id, min(date_column)
from your_table
group by name, id;
If you don't want to use aggregation, you can use FETCH NEXT ROWS WITH TIES:
SELECT tab.*
FROM tab
ORDER BY ROW_NUMBER() OVER(PARTITION BY Name, Id ORDER BY DATE_)
FETCH NEXT 1 ROWS WITH TIES
Output:
NAME
ID
DATE_
Angie
2
02-JAN-23
Austin
3
03-JAN-23
Shane
1
01-JAN-23
Tony
4
05-JAN-23
Check the demo here.

Lag() Function in SQLiteStudio

I am wanting to return the last transaction date grouped by CustomerID, and I am using SQLiteStudio 3.2.1. My table looks like this:
CustomerID Date TransactionID Amount
1 2000-07-01 1 20.00
2 2000-07-04 2 40.00
1 2002-08-01 3 20.00
1 2007-01-01 4 60.00
2 2010-05-09 5 70.00
1 2012-06-25 6 35.00`
This is what I would like the end result to look like: `
CustomerID Date TransactionID Amount Last Transaction Date
1 2000-07-01 1 20.00 NULL
2 2000-07-04 2 40.00 NULL
1 2002-08-01 3 20.00 2000-07-01
1 2007-01-01 4 60.00 2002-01-01
2 2010-05-09 5 70.00 2000-07-04
1 2012-06-25 6 35.00` 2007-01-01
I was attempting to use the following code:
SELECT CustomerID, Date, Amount, LAG(Date,1) OVER (PARTITIONED BY CustomerID ORDER BY Date)
FROM table
However, the lag function is not supported in SQLiteStudio (or maybe I am missing something?). The SQL Editor is also not recognizing the PARTITION BY clause either. Is there a way to use the LAG function or the PARTITION BY clause in the SQL Function Editor? Any help would be greatly appreciated! Thanks!
Also: does anyone have any resources for aggregate function creation in the SQL Function Editor for SQLiteStudio? I know it takes the three parameters of "Initialization code", "Per step code", and "Final step implementation code", but I am looking for examples of the syntax/requirements for these three parameters in SQLiteStudio. (Thanks again!)
Your partition clause, as your pasted above, has a typo, and it should be PARTITION BY, not PARTITIONED BY. If this be the only problem, then just fix the typo:
SELECT CustomerID, Date, Amount,
LAG(Date) OVER (PARTITION BY CustomerID
ORDER BY Date) AS "Last Transaction Date"
FROM yourTable
ORDER BY Date;
If the above still does not work, then perhaps your version of SQLite does not support LAG. One workaround in this case would be to use a correlated subquery in place of LAG:
SELECT CustomerID, Date, Amount,
(SELECT t2.Date
FROM yourTable t2
WHERE t2.CustomerID = t1.CustomerID AND
t2.TransactionID < t1.TransactionID
ORDER BY t2.TransactionID DESC
LIMIT 1) AS "Last Transaction Date"
FROM yourTable t1
ORDER BY Date;

NetSuite: Difference between dates Excluding weekends for transaction formula

Hi I need a formula that will give me the difference in working days (M,T,W,Th) between two dates. So in other words just excluding weekends.
My current formula is: ROUND({systemnotes.date}-{trandate})
This works great except for that it counts Saturday and Sunday.
Thanks for the help!
Here is a formula that will get you the difference between two dates excluding Saturday and Sunday as a number of days. Put this into a formula(numeric) field in your search.
ROUND(((TO_CHAR({systemnotes.date}, 'J') - TO_CHAR({trandate}, 'J'))) + MOD(({systemnotes.date} - {trandate}), 1) - ((((TRUNC({systemnotes.date}, 'D')) - (TRUNC({trandate}, 'D')))/7)*2) - (CASE WHEN TO_CHAR({trandate}, 'DY') = 'SUN' THEN 1 ELSE 0 END) - (CASE WHEN TO_CHAR({systemnotes.date}, 'DY') = 'SAT' THEN 1 ELSE 0 END), 2)
Sorry, it's a bit of a long one, but in the formula {systemnotes.date} is your start date and {trandate} is your end date.

Change the year of a date to the current year in PL/SQL

I'm currently trying to do a comparison in my select. If the current date is before August 1st of the current year then display august 1st of the last year, otherwise display august 1st of this year. Essentially I'm trying to do:
CASE
WHEN (SYSDATE < 08/01/2015) THEN
08/01/2014
ELSE
08/01/2015
But I am at a loss as to how to get august for the month. So far I have:
TRUNC(SYSDATE, 'MON')
To get /01/ but how would I get it to constantly return august as the month? Would it be better to hardcode in the date and month and dynamically get the year instead? like 01/08/
Try something like this:
1 select sysdate,
2 trunc(sysdate,'YEAR'),
3 add_months(trunc(sysdate,'YEAR'),7),
4 add_months(trunc(sysdate,'YEAR'),7-12)
5* from dual
SQL> /
SYSDATE TRUNC(SYSDA ADD_MONTHS( ADD_MONTHS(
----------- ----------- ----------- -----------
31-jul-2015 01-jan-2015 01-aug-2015 01-aug-2014
SQL>
the columns are:
1) pulling the current sysdate.
2) converting to the first day of the year.
3) adding 7 months to get Aug 1 of current year.
4) -12 months to get Aug 1 of last year.
(that shows you the usage, you can figure out how to plug those suckers into your CASE statement ;) )

Range of Week instead of be putting dates

I have below query but instead of to be putting range of week like '22-OCT-2012 AND 28-OCT-2012' I woulk to put a code like CurrentWeek -2 or CurrentWeek-1, that will avoid to edit the query every week that I need to run it.
Do you know how make this?
tHANKS
LD
SELECT WO.USER_6 AS STYLE
,SUM (CASE WHEN (OPERATION.STATUS ='C' AND OPERATION.CLOSE_DATE BETWEEN '22-OCT-2012' AND '28-OCT-2012') THEN OPERATION.RUN_HRS ELSE 0 END) WEEK43
,SUM (CASE WHEN (OPERATION.STATUS ='C' AND OPERATION.CLOSE_DATE BETWEEN '29-OCT-2012' AND '04-NOV-2012') THEN OPERATION.RUN_HRS ELSE 0 END) WEEK44
FROM WORK_ORDER WO, OPERATION
WHERE WO.BASE_ID = OPERATION.WORKORDER_BASE_ID
AND WO.Lot_ID = Operation.Workorder_Lot_ID
AND WO.Sub_ID = Operation.Workorder_Sub_ID
AND WO.Split_ID = Operation.Workorder_Split_ID
AND WO.TYPE ='W'
AND WO.WAREHOUSE_ID ='MEX-04'
AND OPERATION.CLOSE_DATE BETWEEN '22-OCT-2012' AND '04-NOV-2012'
AND OPERATION.RESOURCE_ID IN ('171-4','171-ADD','171-3' ,'BAMEX-SEWCONC','BAMEX-SEWPATC')
AND OPERATION.RUN > 0
GROUP BY
WO.USER_6
If I understood your question then u can use this to pass the current week days like this
SUM (CASE WHEN (OPERATION.STATUS ='C' AND OPERATION.CLOSE_DATE BETWEEN to_char(trunc(sysdate),'DD-MON-YYYY') and to_char(trunc(sysdate)-6,'DD-MON-YYYY')) THEN OPERATION.RUN_HRS ELSE 0 END) WEEK43
Hope this help u
In this case I will use trunc function:
currentweek will be trunc(sysdate,'D')
current_week - 1 will be trunc(sysdate,'D') - 7
current week - 2 will be trunc(sysdate,'D') - 2 * 7
Attention this will give first day of week sunday. If you want monday you should and one day:
current week - 2 will be trunc(sysdate,'D') - 2 * 7 + 1
UPDATE:
Frank is right, the behavior on first day of week depends on NLS_TERITORY
alter session set NLS_TERRITORY ='UNITED KINGDOM';
select trunc(sysdate,'D') from dual;
05-11-2012
alter session set NLS_TERRITORY ='AMERICA';
select trunc(sysdate,'D') from dual;
04-11-2012

Resources