I have new users being added to my table each day and I want to check for new users. However, the table's data removes old rows after reaching a certain number of rows. To keep my new rows accurate, I want to calculate the new users BASED on the PREVIOUS ROWS values. So as long as I have one previous row available, my new row will always be accurate. If there is no previous row, the row should have a default value.
Date
users_Today
New_users
All_users_To_Date
Dec 6
Allie, Jon
Allie, Jon
Allie, Jon
Dec 7
Allie, Jon, Zach
Zach
Allie, Jon, Zach
Currently I have:
WITH user_log_response AS (
SELECT
CAST(JSON_PARSE(user_log) AS MAP<VARCHAR, VARCHAR>) AS user_map,
date
FROM user_log_response_table
),
names_and_dates AS (
SELECT DISTINCT
user_name AS user_name,
date
FROM user_log_response
CROSS JOIN UNNEST(user_map) AS u(user_name, user_age)
),
user_names AS (
SELECT
date,
ARRAY_JOIN(
ARRAY_AGG(
user_name
ORDER BY
user_name
),
','
) users_today,
FROM names_and_dates
GROUP BY
date
ORDER BY
date DESC
)
SELECT
date,
users_today
FROM user_names
Which results in this
Date
users_Today
Dec 6
Allie, Jon
Dec 7
Allie, Jon, Zach
If I store "all users to date" how can I calculate "new users" to equal previous row's "all users to date" minus "users today"
Also how can I calculate "all users to date" to equal previous row's "all users to date" plus current row's "new users"
Related
I am using Orcle sql developer to access an MSsql database. I have week number field. and I want to extract all information that the week no is equal to the week number of today's date.
Sample Data
DutyStaff Address WeekNo Contact
John 35thd 15 670956
Peter 25 str 19 706346
Chris 40 odr 20 856294
Adam 7thstr 34 567251
Mary 6thstr 22 702457
I want to extract all rows that have the week number of today. Select * where weekno = (today's week number). The week number of today 12/05/2022 is 19 i.e current day week number
select * from <table_name> as t where t.week_no = ;
will give you all the info specific to the chosen week.
Also;
select * from <table_name> as t groupby t.week_no;
will group all info pertaining to a particular week as one.
From my understanding, this is what you were asking for, I think.
I have a situation where I need to store day and date(just a date) in single column in Oracle as below:
Column name
Monday
Tuesday
25
10
But I don't like combining string and number in single column. So I want any formula or design where each of these values gets unique identifier and store like below:
Column name
1 - - - - - refers to Monday
2............refers Tuesday
3-----------refers to a actual date 1
Above is an imaginary values just for understanding.
What I need is if have to get all entries with value Monday I should apply some formula and get a number which I should use in select query
Same way if I want to select entries with date =25 then I have to apply same formula and get unique number that represents date 25 and use it in my query
Store only the DATE in a column, the day of week is derived from that.
so:
CREATE TABLE junk
(
id number,
my_date date
);
insert into junk values ( 123, sysdate );
insert into junk values ( 234, add_months(sysdate,-123) );
commit;
select my_date "The actual date",
to_char(my_date,'Day') "The day of the week",
to_char(my_date,'Dy') "other way",
to_char(my_date,'D') "another way"
from junk;
The actual date The day o oth a
-------------------- --------- --- -
27-mar-2019 15:28:15 Wednesday Wed 4
27-dec-2008 15:28:15 Saturday Sat 7
2 rows selected.
Trying to do anything more than that, you will likely only hurt yourself in the long run (consider how you will maintain things if something is updated .. consider what happens if/when somebody "accidentally" updates 1 of the values, without updating the matching one? ... because they didn't understand it ... )
-- only pull records on Wednesday
select *
from junk
where to_char(my_date,'D') = 4
/
ID MY_DATE
---------- --------------------
123 27-mar-2019 15:28:15
1 row selected.
You can use the to_char() function in oracle:
SELECT TO_CHAR(date '2019-03-27', 'DAY') day FROM dual;
Which will return the day of the week.
I would like to make a calculation to get the difference between the departDate from my current row and the arriveDateNextStop from my previous row. I have a fact table which has multiple columns. The three most important columns are: id, departDate, arriveDateNextStop.
If I have for example these two rows in my fact table:
id departDate arriveDateNextStop
1 01-01-2019 03-01-2019
1 04-01-2019 07-01-2019
Explanation: On 1 January 2019 I depart to the next destination and I arrive there on 3 January 2019. On 4 January 2019 I again depart to the next destination and I arrive there on 7 January 2019.
Now I would like to know how many days the idle time was (the amount of days between the arrival and the next depart). So with this example the idle time would be 1, because between 3 January 2019 and 4 January 2019 is one day.
First, I made this 'calculation' in Management Studio as a SQL query. See query below:
SELECT s.Id, s.departDate as Depart_current_place, s.arriveDateNextStop as Arrival_next_stop, LAG(arriveDateNextStop) OVER (ORDER BY arriveDateNextStop) AS Arrival_current_stop, DATEDIFF(DAY, LAG(arriveDateNextStop) OVER (ORDER BY arriveDateNextStop), departDate) AS Amount_of_days
FROM MyTable s
WHERE Id = 9
GROUP BY s.departDate, s.Id, s.arriveDateNextStop
ORDER BY s.departDate
This query works fine, but how can I do this in my cube as a calculation in MDX?
I don't have the same example, but the similar cube structure with Completed/Received date:
with
member departDate as [Received].[Year Qtr Month].CurrentMember.Member_Key
member arriveDate as [Completed].[Year Qtr Month].CurrentMember.Member_Key
member arriveDateNextStop as [Completed].[Year Qtr Month].CurrentMember.Lead(1).Member_Key
member idleDays as departDate-arriveDateNextStop
SELECT NON EMPTY { departDate,arriveDate,arriveDateNextStop,idleDays } ON 0
, NON EMPTY
{ ([Completed].[Year Qtr Month].[Date].ALLMEMBERS
* [Received].[Year Qtr Month].[Date].ALLMEMBERS ) } ON 1
FROM ( SELECT ( { [Completed].[Year Qtr Month].[Date].&[6213] } ) ON COLUMNS
FROM [MyCube])
I also have integer key for a date dimension (CurrentMember.Member_Key). 1 = 1998-01-01, 2 = 1998-01-02 etc. till today. You need to create a property in a Date dimension if your Date key is classic YYYYMMDD (which you cannot subtract to get days difference, I can do that in my example). And use it like CurrentMember.Properties("property name") instead of Member_Key.
Main formula part: Lag/Lead function to get prev. or next member.
Please update in case of questions.
I have a table called as Activity with columns like activity_id and activity_date.
Consider a data in activity table like below,
activity_id activity_date
1 1st June
2 1st July
3 1st August
4 1st September
5 1st October
Now I want to change the date of the activity 3, but I can not change the date to less than 1st July or more than 1st September as there are already some other activities on those dates.
The only valid dates for activity 3 are between 2nd July to 30th August.
Similarly, for activity 1, valid new date can be any date before 1st July.
Similarly, for activity 5, valid new date ranges from 2nd September to any date in future as its last activity.
I need to give the validation message to the user in front end if the new date is not within the range.
Input to the query will be activity id and the new activity date.
Below is the DDL script
CREATE TABLE "HEADCOUNT"."ACTIVITY"
( "ACTIVITY_ID" NUMBER(*,0) NOT NULL,
"ACTIVITY_DATE" DATE
);
Insert into "HEADCOUNT"."ACTIVITY" (ACTIVITY_ID,ACTIVITY_DATE) values (1,'01-06-2012');
Insert into "HEADCOUNT"."ACTIVITY" (ACTIVITY_ID,ACTIVITY_DATE) values (2,'01-07-2012');
Insert into "HEADCOUNT"."ACTIVITY" (ACTIVITY_ID,ACTIVITY_DATE) values (3,'01-08-2012');
Insert into "HEADCOUNT"."ACTIVITY" (ACTIVITY_ID,ACTIVITY_DATE) values (4,'01-09-2012');
Insert into "HEADCOUNT"."ACTIVITY" (ACTIVITY_ID,ACTIVITY_DATE) values (5,'01-10-2012');
This will find the date ranges for each row:
SELECT activity_id, activity_date
,NVL( LAG(activity_date) OVER(ORDER BY activity_id)
,TO_DATE('1900-01-01', 'YYYY-MM-DD')
) AS previous_date
,NVL( LEAD(activity_date) OVER(ORDER BY activity_id)
,TO_DATE('2100-01-01', 'YYYY-MM-DD')
) AS next_date
FROM activity
ORDER BY activity_id
Result:
ACTIVITY_ID ACTIVITY_DATE PREVIOUS_DATE NEXT_DATE
---------------------------------- ------------- ------------- ---------
1 01-JUN-12 01-JAN-00 01-JUL-12
2 01-JUL-12 01-JUN-12 01-AUG-12
3 01-AUG-12 01-JUL-12 01-SEP-12
4 01-SEP-12 01-AUG-12 01-OCT-12
5 01-OCT-12 01-SEP-12 01-JAN-00
Validation would then be for a given id:
"input date" > previous_date AND "input date" < next_date
Date ranges are based on previous and following records when ordered by activity_id. Perhaps the ordering should really be by activity_date, though. Using LAG and LEAD will allow for gaps in activity_ids as well.
Find date limits using a query like below (replace #param_id with changing activity id):
SELECT activity_id, activity_date
FROM activity
WHERE activity_id = #param_id-1
OR activity_id = #param_id+1
This query will return at most two results, but for first and last activities only one will be returned. So, you should read results in the front-end and decide what to do:
Specify beginning limit: Result with id #param_id-1 specifies beginning date limit. If no result with this id, this is first activity and no limit for begin date.
Specify ending limit: Result with id #param_id+1 specifies ending date limit. If no result with this id, this is last activity and no limit for end date.
Do or warn: If new date is within the range, perform change. Otherwise warn the user.
I have a table say EmployeeAbsence that has three columns: EmployeeId, LeaveReason and Date. This table records attendance of employees on a daily basis. I want to know the list of employees who took leave in last 14 days.
For example,
1 XYZ 2009-07-20
2 XYZ 2009-07-19
--
---
--
1001 XYZ 2009-07-04
In this case, my query output should return XYZ and alike because it contains entries for employees who were absent for last 14 days consecutively. I would appreciate an ORACLE query.
Your query will need two constraints
Data of leave must be less than 14 days away from current date
Employee has to appear only once if they have been on leave for several days / times during the 14 day period
For constraint (1) you need to know that subtracting date A from date B results in the number of days between those two dates.
For constraint (2) you need to group by the employees ID.
That said
SELECT EmployeeID
FROM EmployeeAbsence
WHERE Date between SYSDATE - 14 and SYSDATE
GROUP BY EmployeeId
should do the trick.
I assume that table has 1 record for each day of absence and you don't want to retrieve employees that were absent for e.g. last month but returned during last 14 days.
SELECT employeeId
FROM employeeAbsences base
WHERE date > trunc(sysdate)-15 -- we want to include one more day for HAVING clause to work with
GROUP BY employeeId
-- had 2 or more non-consecutive leaves --> at least one of them started during last 14 days
HAVING count(*) < max(date) - min(date)
-- first absence is less than 14 days ago
OR min(date) > trunc(sysdate) - 14;