Select Max and Min datetime - sql

I have a record as below
Login Time Logout Time User Shift
2017-04-01 21:30:00.000 2017-04-02 00:00:00.000 I0402 N
2017-04-02 00:00:00.000 2017-04-02 00:30:00.000 I0402 N
2017-04-02 01:30:00.000 2017-04-02 05:30:00.000 I0402 N
2017-04-02 06:30:00.000 2017-04-02 08:30:00.000 I0402 N
I want to get the earliest entry time and latest logout time for the user. How I can do this?
The record I wish to as below
Login Time Logout Time User Shift
2017-04-01 21:30:00.000 2017-04-02 08:30:00.000 I0402 N
Is it possible to do that?
Thanks.
Edit
I try before with Max and Min and group by User and Shift, it is work. If it is more than 1 days record, it seem like not work
2017-04-01 21:30:00.000 2017-04-02 00:00:00.000 I0402 N
2017-04-02 00:00:00.000 2017-04-02 00:30:00.000 I0402 N
2017-04-02 01:30:00.000 2017-04-02 05:30:00.000 I0402 N
2017-04-02 06:30:00.000 2017-04-02 08:30:00.000 I0402 N
2017-04-02 21:30:00.000 2017-04-03 00:00:00.000 I0402 N
2017-04-03 00:00:00.000 2017-04-03 00:30:00.000 I0402 N
2017-04-03 01:30:00.000 2017-04-03 05:30:00.000 I0402 N
The expected result as below
2017-04-01 21:30:00.000 2017-04-02 08:30:00.000 I0402 N
2017-04-02 21:30:00.000 2017-04-03 05:30:00.000 I0402 N

SELECT
User
,MIN(Login Time)
,MAX(Logout Time)
,Shift
FROM
dbo.table
GROUP BY
User,Shift

I try before with Max and Min and group by User and Shift, it is work. If it is more than 1 days record, it seem like not work
2017-04-01 21:30:00.000 2017-04-02 00:00:00.000 I0402 N
2017-04-02 00:00:00.000 2017-04-02 00:30:00.000 I0402 N
2017-04-02 01:30:00.000 2017-04-02 05:30:00.000 I0402 N
2017-04-02 06:30:00.000 2017-04-02 08:30:00.000 I0402 N
2017-04-02 21:30:00.000 2017-04-03 00:00:00.000 I0402 N
2017-04-03 00:00:00.000 2017-04-03 00:30:00.000 I0402 N
2017-04-03 01:30:00.000 2017-04-03 05:30:00.000 I0402 N
The expected result as below
2017-04-01 21:30:00.000 2017-04-02 08:30:00.000 I0402 N
2017-04-02 21:30:00.000 2017-04-03 05:30:00.000 I0402 N

You can use below query to get the result,
SELECT T1.USER, T2.MAX_LOGIN_TIME, T3.MIN_LOGIN_TIME FROM
TABLE_NAME T1
INNER JOIN (SELECT MAX(LOGIN_TIME) AS MAX_LOGIN_TIME,USER FROM TABLE_NAME
GROUP BY USER) T2
ON (T1.USER = T2.USER)
INNER JOIN (SELECT MIN(LOGIN_TIME) AS MIN_LOGIN_TIME,USER FROM TABLE_NAME
GROUP BY USER) T3
ON (T1.USER = T3.USER);

It seems what you really want is one result row per day, user and shift. So group by these and take min and max time.
select min(Login_time) as login, max(logout_time) as logout, user, shift
from mytable
group by date(login_time), user, shift
order by date(Login_time), user, shift;
Here DATE(login_time) is just an example. How to get the date from a datetime differs from DBMS to DBMS. Look up date/time functions for your DBMS to get the appropriate function.

Related

get time series in 8 hours of interval

I am generating one time-series from using the below query.
SELECT * from (
select * from generate_series(
date_trunc('hour', '2021-11-13 10:01:38'::timestamp),
'2021-12-13 10:01:38'::timestamp,
concat(480, ' minutes')::interval) as t(time_ent)) as t
where t."time_ent" between '2021-11-13 10:01:38'::timestamp and '2021-12-13 10:01:38'::timestamp
and it will give me output like below.
2021-11-13 18:00:00.000
2021-11-14 02:00:00.000
2021-11-14 10:00:00.000
2021-11-14 18:00:00.000
2021-11-15 02:00:00.000
but I need output like.
2021-11-13 16:00:00.000
2021-11-14 00:00:00.000
2021-11-14 08:00:00.000
2021-11-14 16:00:00.000
2021-11-15 00:00:00.000
currently, the time series hours depend upon the timestamp that I pass. in above it gives me hours like 02,10,18...but I want the hours like 00,08,16...hours should not depend on the time I passed in query. I tried many things but not any success.
as your start of generate_series is set to 10:00:00, so your next step will be 18:00:00
you have to start your serie from 00:00:00 (cast to date) e.g.:
SELECT
time_ent::timestamp without time zone
from (
select * from generate_series(
date_trunc('hour', '2021-11-13 10:01:38'::date),
'2021-12-13 10:01:38'::timestamp ,
concat(480, ' minutes')::interval) as t(time_ent)
) as t
where t."time_ent" between '2021-11-13 10:01:38'::timestamp and '2021-12-13 10:01:38'::timestamp
and the result will be:
2021-11-13 16:00:00.000
2021-11-14 00:00:00.000
2021-11-14 08:00:00.000
2021-11-14 16:00:00.000
2021-11-15 00:00:00.000
2021-11-15 08:00:00.000

Remove rows with overlapping date ranges

I have a table with start_date and end_date columns and I want to remove records where both start_date and end_date are in an existing date range
source data:
start_date end_date
2019-03-18 00:00:00.000 2019-04-08 00:00:00.000
2019-04-01 00:00:00.000 2019-05-31 00:00:00.000
2019-04-03 00:00:00.000 2019-04-24 00:00:00.000
2019-04-24 00:00:00.000 2019-05-05 00:00:00.000
2019-05-06 00:00:00.000 2019-05-16 00:00:00.000
2019-05-06 00:00:00.000 2019-05-20 00:00:00.000
2019-05-06 00:00:00.000 2019-06-17 00:00:00.000
2019-05-10 00:00:00.000 2019-05-14 00:00:00.000
expected result:
start_date end_date
2019-03-18 00:00:00.000 2019-04-08 00:00:00.000
2019-04-01 00:00:00.000 2019-05-31 00:00:00.000
2019-05-06 00:00:00.000 2019-06-17 00:00:00.000
Well it's really not that hard, you just check for literally the thing you want to check for. Simply verify there aren't any records that would would contain your start date and end date between their own start and end date.
Something like this will work:
select *
from so_58088216 wrapping
where not exists (select *
from so_58088216 wrapped
where wrapping.start_date between wrapped.start_date and wrapped.end_date
and wrapping.end_date between wrapped.start_date and wrapped.end_date
-- don't check against yourself, this would be easier if had an ID or something
and wrapping.start_date != wrapped.start_date
and wrapping.end_date != wrapped.end_date)
Here's a working example

Select data between night and day hours

My data looks like this, it is a minute based data for 2 years.
2017-04-02 00:00:00
2017-04-02 00:01:00
2017-04-02 00:02:00
2017-04-02 00:03:00
2017-04-02 00:04:00
....
2017-04-02 23:59:00
...
2019-02-01 22:54:00
2019-02-01 22:55:00
2019-02-01 22:56:00
2019-02-01 22:57:00
2019-02-01 22:58:00
2019-02-01 22:59:00
2019-02-01 23:00:00
I want to access all the data rows between the end of the workday to the beginning of the next. Example between 2018-04-02 18:00:00 2018-04-03 05:00:00 for all the days in my data frame. Please help
If you use a DatetimeIndex then you can use .between_time
import pandas as pd
df = pd.DataFrame({'date': pd.date_range('2017-04-02', freq='90min', periods=100)})
df = df.set_index('date')
df.between_time('18:00', '5:00')
#date
#2017-04-02 00:00:00
#2017-04-02 01:30:00
#2017-04-02 03:00:00
#2017-04-02 04:30:00
#2017-04-02 18:00:00
#2017-04-02 19:30:00
#2017-04-02 21:00:00
#2017-04-02 22:30:00
#....
One approach is boolean indexing based on conditions on the datetime column or index. Assuming your DataFrame is named df and it has a DatetimeIndex equal to the example data you've posted, try this:
df[(df.index.hour >= 18) | (df.index.hour <= 5)]

Sum where values of a column matches without number of rows changing

I am trying to values of a column where values of another column matches. Below is a sample of my data.
DT No_of_records LD_VOY_N LD_VSL_M
2017-05-06 04:00:00.000 7 0002W pqo emzmnwp
2017-05-06 20:00:00.000 6 0002W pqo emzmnwp
2017-05-02 04:00:00.000 1 0007E omq ynzmeoyn
2017-05-01 08:00:00.000 2 0016W rmhp sunhpnw
2017-05-01 12:00:00.000 1 0016W rmhp sunhpnw
2017-05-05 12:00:00.000 2 0019N omq wqmsy
2017-05-06 04:00:00.000 12 0019N omq wqmsy
Below is my desired output
DT No_of_records LD_VOY_N LD_VSL_M Total_no_of_records
2017-05-06 04:00:00.000 7 0002W pqo emzmnwp 13
2017-05-06 20:00:00.000 6 0002W pqo emzmnwp 13
2017-05-02 04:00:00.000 1 0007E omq ynzmeoyn 1
2017-05-01 08:00:00.000 2 0016W rmhp sunhpnw 3
2017-05-01 12:00:00.000 1 0016W rmhp sunhpnw 3
2017-05-05 12:00:00.000 2 0019N omq wqmsy 14
2017-05-06 04:00:00.000 12 0019N omq wqmsy 14
I am trying to find the Total_no_of_records column. Do you have any ideas?
You seem to want a window function by LD_VOY_N:
select t.*,
sum(No_of_records) over (partition by LD_VOY_N) as Total_no_of_records
from t;
select DT,No_of_records,LD_VOY_N,LD_VSL_M ,COUNT(DISTINCT (DT,No_of_records,LD_VOY_N,LD_VSL_M )) as Total_no_of_records from tablename
group by DT,No_of_records,LD_VOY_N,LD_VSL_M

joining monthly values with daily values in sql

I have daily values in one table and monthly values in another table. I need to use the values of the monthly table and calculate them on a daily basis.
basically, monthly factor * daily factor -- for each day
thanks!
I have a table like this:
2010-12-31 00:00:00.000 28.3
2010-09-30 00:00:00.000 64.1
2010-06-30 00:00:00.000 66.15
2010-03-31 00:00:00.000 12.54
and a table like this :
2010-12-31 00:00:00.000 98.1
2010-12-30 00:00:00.000 97.61
2010-12-29 00:00:00.000 99.03
2010-12-28 00:00:00.000 97.7
2010-12-27 00:00:00.000 96.87
2010-12-23 00:00:00.000 97.44
2010-12-22 00:00:00.000 97.76
2010-12-21 00:00:00.000 96.63
2010-12-20 00:00:00.000 95.47
2010-12-17 00:00:00.000 95.2
2010-12-16 00:00:00.000 94.84
2010-12-15 00:00:00.000 94.8
2010-12-14 00:00:00.000 94.1
2010-12-13 00:00:00.000 93.88
2010-12-10 00:00:00.000 93.04
2010-12-09 00:00:00.000 91.07
2010-12-08 00:00:00.000 90.89
2010-12-07 00:00:00.000 92.72
2010-12-06 00:00:00.000 93.05
2010-12-03 00:00:00.000 91.74
2010-12-02 00:00:00.000 90.74
2010-12-01 00:00:00.000 90.25
I need to take the value for the quarter and multiply it buy all the days in the quarter by the daily value
You could try:
SELECT dt.day, dt.factor*mt.factor AS daily_factor
FROM daily_table dt INNER JOIN month_table mt
ON YEAR(dt.day) = YEAR(mt.day)
AND FLOOR((MONTH(dt.day)-1)/3) = FLOOR((MONTH(mt.day)-1)/3)
ORDER BY dt.day
or (as suggested by #Andriy)
SELECT dt.day, dt.factor*mt.factor AS daily_factor
FROM daily_table dt INNER JOIN month_table mt
ON YEAR(dt.day) = YEAR(mt.day)
AND DATEPART(QUARTER, dt.day) = DATEPART(QUARTER, mt.day)
ORDER BY dt.day