Counting Records Over a Rolling Period of Time SQL (Based on Last Record) - sql

I'm relatively new to SQL and trying to pull the following from an Oracle SQL database.
Let's say I have a table of users and the time that they logged in that looks like this:
Name LOG_IN
Jim 13:00:05
Patrick 13:02:23
Steve 13:02:44
Emma 13:03:16
Steve 13:04:44
Jim 13:04:05
Jim 13:05:05
Jim 13:05:06
Patrick 13:05:17
Emma 13:05:18
Steve 13:08:13
Say I want to run a report which tells me their last user login in and all logins that happened within a timeframe of 5 minutes before the last login. If I was doing this in another language, I would just a for .. loop to get the last login and then count back to previous logins and compare if the login time falls within the 5 min window. I am unsure how I would accomplish the same thing with Oracle SQL. For example, for someone like Jim, his last login is at 13:05:06 so I would want all the times he logged in between 13:00:06 and 13:05:06, which would be:'
Name LOG_IN
Jim 13:04:05
Jim 13:05:05
Jim 13:05:06
So the very first login (at 13:00:05) would not be included because it's not in the range.
The same report would return results for the other users as well, so for Steve, the following would be returned:
Name LOG_IN
Steve 13:04:44
Steve 13:08:13
And the first login (at 13:02:44) would not be returned.
When I first looked at this, I thought the requirement was to pull all transactions within a 5 minute of the time of the report, but I have since learned I need to do this rolling period calculation based on last login.

select Name, LOG_IN
from <table_name> A where LOG_IN >
(select max(LOG_IN) from <table_name> where Name=A.Name)-(1/24./60.*5.);
Here's a sqlfiddle link:
http://sqlfiddle.com/#!4/b231e/11/0
(don't know how long it will be persistent...)

Related

I am wondering if there is an elegant way to apply either a combination of query, Arrayformula, sort, functions in Google Sheets to do the following

Google Sheets Problem. I have a master list that has columns which are employers, job post, # of spots, parameter x, parameter y,...etc.
"Master Sheet" #a tab
Employers Job Spots
John Cleaner 1
Mike Cleaner 2
John Cleaner 3
John Server 5
Alice Cook 1
Dave Cook 1
Mary Cleaner 3
Alice Server 5
Alice Cleaner 2
Dave Server 4
Mike Server 3
Alice Server 1
This is what I would like "Output Sheet" #another tab with two columns. 1st is Jobs and 2nd is # of employers that account for 80% of the jobs in that category plus any additional filters. The idea is to give a single # that gives an 80/20 rule type metric. The trick is to Sort one column from highest to lowest first. I can do this but in multiple steps that seem annoyingly inefficient. I wonder if there is a better way where I can put everything in one cell and drag down or do a query function. The output looks like below.
Job # of employers that account for ~80% of all the jobs in that category + filters
Cleaner ~3
Cook 1
Server ~3
#because total Cleaner jobs is 11. 80% is 8.8. And sorting employers highest to lowest (after accounting for duplicates), 3 employers represent 80% of the Cleaner jobs available. Server total is 21, 80% is 16.8, so ~3 employers represent 80% of the Server jobs available.
Thank you all for your help.
To take 80%:
=query(A15:C26, "Select B, sum(C)*8/100 group by B label B 'Job'")
you will get
{0.88, 0.16, 1.44)
But the next you can continue by yourself

SQL - selecting multiple dates from a table for unique ID's - part 2

Gordon got me pretty straight on my former question and now I've learned a lot more :). my query now looks like this:
select ident, min(input_date) as 'date requested',
min(case when op='u' and user IN (lists tech's names)) as 'date assigned'
max(case when status='closed' then date end) as 'date completed'
max(case when op='u' then user end) as 'tech'
from table
so this give me all that i want except the column that's labelled as 'tech'. for the majority of the results, i get the correct results but for a handful it gives me either the wrong tech or the 'user'
so I've added a field so you can better understand - it's field called 'role'. when i run this query, i never want the person listed as 'user' in the role column to be listed as 'tech'. in query above, it lists the user instead of tech and it's always in cases where the user updated their request. so if you look at the table, in ident 1, tom is user and harry is tech. harry assigned it to himself on 2/2; however, tom updated request (to give more info) after harry assigned it. running the above query, will result in tom being listed as the tech in the tech field. my guess is b/c of max and tom is after harry alphabetically.
so i have 5 tech's to track (only 2 listed in table - bertha & harry). if i add an IN clause so that it reads like this:
max(case when op='u' and user IN ('bertha','harry',etc) then user end) as 'tech'
the results is it always gives me the last tech alphabetically rather than the one who assigned it/closed it.
my goal is to have the tech who assigns & closes it to be listed. if the request has not been assigned then the 'tech' field should read null.
the date fields all have time stamps so i could go about it that way and i guess i could target their role as well.
i know that max is probably the problem as the tech could assign it then the user could update but if i put IN statement in there I don't get why it lists a tech who's not associated w/that ident.
finally, the other scenario, in ident 2, bertha actually takes the assignment away from harry so i need to say bertha; however, harry will always be the one reported in field - probably due to max()
thanks

Excel 2013 VLOOKUP() based on multiple criteria, retrieving multiple rows

I have an issue that can (I believe) be solved by just excel, and may won't require VBA (I could be wrong). I believe it can be solved by nested functions but the formula I've tried has not worked.
Here's my data:
Name Report # Name
Mark Doe ReportXXX Mark Doe
Connie Doe ReportYYY Connie Doe
Debbie Doe REPORTYYY Debbie Doe
Valerie Doe FSMVALTR1 Valerie Doe
Jeff Doe FSMVALTR1 Jeff Doe
Andy Doe RAZXYBCA1 Andy Doe
Ryan Doe RAZXYBCA1 Ryan Doe
Andy Doe RAZ111111 Jill Doe
Ryan Doe RAZ222112 Amanda Doe
This list goes on for about ~4000 rows in the first NAME and REPORT # columns. In the second NAME column I have ~160 rows.
The second name column identifies all the users who actually use the report, with no duplicates. The two name and report # columns have many duplicates, since users have access to multiple reports, and many of them are the same report used for different purposes. Since the second NAME column has so few rows, the names don't match up all the way through, which can be observed near the bottom of both the NAME columns.
What I need to do is have a VLOOKUP that identifies the name in both of the columns and then returns the report number that each individual has access to across rows (horizontally), not down the columns. It also needs to I.D. numerous reports since individuals have access to anywhere from 1-15 reports, starting at the second and so on after the previous has been extracted.
Ideally it would look something like this:
Name Report # Name ex column ex column ex column
Mark Doe ReportXXX Mark Doe ReportXXX ReportAAA ReportB
I didn't list the other reports "Mark Doe" has access to and these would be somewhere down the long list of ~4000, along with his name repeated multiple times in the first NAME column, but the second "unique" name column would be where it is returning the reports to, across rows.
I made a method that uses additional three columns and it worked for me.
I used the data you provided above.
Add three columns to the left.
in A2 enter =COUNTIFS($D$2:$D2,D2,$E$2:$E2,E2).
in B2 enter =SUMIFS($A$2:$A2,$A$2:$A2,1,$D$2:D2,D2).
in C2 enter =D2&B2.
Now copy those cells to all your 4000 rows.
Now next to the second name column add column headers numbered from 1 to as many reports you think can be the max one user can have (you said 15).
Now enter this vlookup in F2 =IFERROR(VLOOKUP($F2&G$1, your table array starting from column C as absolute/fixed ,3,FALSE),"") in my case it was =IFERROR(VLOOKUP($F2&G$1,$C$2:$E$11,3,FALSE),"").
Copy the formula accross all columns with number headers and down all rows that have names in second name column (160).
your sheet shuld look something like this image
All the best let me know if it worked for you.
Have you explored the option of using a Pivot Table?
The output would look like this:
With the Pivot Table setup like this:
This method would make for a cleaner view, as your current method looks to repeat ~4,000 times (once for each report & name combo). Hopefully this works for what you need.

finding time concurrency with an oracle select

I have the following data in a DB table and would like to find concurrent transactions based on the start and end time.
Patient Start Time End Time
John 08:31A 10:49A
Jim 10:14A 10:30A
Jerry 10:15A 10:28A
Alice 10:18A 12:29P
Bobby 10:32A 10:49A
Sally 10:46A 10:55A
Jane 10:52A 11:29A
Jules 10:54A 11:40A
Adam 10:58A 11:25A
Ben 11:00A 11:20A
Ann 11:31A 11:56A
Chris 11:49A 11:57A
Nick 12:00P 12:21P
Dave 12:00P 12:35P
Steve 12:23P 12:29P
If I want to find any overlapping times with a particular input, how would I write it? For example say I want to find overlaps with the 10:58A-11:25A time. This needs to find potential time concurrencies. I am looking for a count of the maximum number of concurrent overlaps. In my example for 10:58A-11:25A, I would want to see the following (count would be 5):
Patient Start Time End Time
Alice 10:18A 12:29P
Jane 10:52A 11:29A
Jules 10:54A 11:40A
Adam 10:58A 11:25A
Ben 11:00A 11:20A
In my second example some of the concurrent times overlap with the time I am looking for, but they are over before another range start. So, say I am looking for 10:46A-10:55A. I would expect a count of 4. In this example 08:31A-10:49A is dropped because it is over before 10:52A-11:29A starts. Same with 10:32A-10:49A, it was over before 10:52A-11:29A started. So, the most concurrent with the 10:46A-10:55A range would be 4, even though overall there is 6 (2 dropped).
Patient Start Time End Time
Alice 10:18A 12:29P
Sally 10:46A 10:55A
Jane 10:52A 11:29A
Jules 10:54A 11:40A
Can this be done with a sql statement?
The most easy and clean method is to exclude rows:
All rows except:
rows than ends before start time
rows than begins after end time
sample:
select * from your table t
where
not (
t.end < begin_time
or
t.start > end_time
)
Sample in sqlfiddle

SQL Query Data Collect

I have a SQL server table that has a list of Usernames and a list of points ranging from 1 to 10,000.
I want to display the number of points in my VB.NET program from the username given. For example, if I type in "john" in the first box the program will give me a message box saying whatever amount of points "john" has. I'm not really sure about SQL queries so please help me out here.
This is the Table Structure:
Usernames Points
-----------------------------
John 20
Kate 40
Dan 309
Smith 4958
Depending on the structure of the table, a suitable query is one of these:
select sum(points) as points
from usernames
where name='username';
or
select points
from usernames
where name='username';
or
select count(*) as points
from usernames
where name='username';