selecting values in same time period sqlite - sql

Consider Table Events
Date Time Duration Event
1-1-2023 20:28:00 95 A
1-1-2023 20:29:00 60 B
1-1-2023 20:29:55 10 C
1-1-2023 21:12:00 2 D
...
Now i want to get entries happening in same time period, so for example activity A happens from 20:28:00 to 20:29:35, and activity B happens in time period of 20:29:00 to 20:30:00
So Event A and B have common 35 seconds and B and C has common 5 secs.
i want to get all events in common time period, is it possible using just sql query?

Assuming that your dates are in the proper ISO format YYYY-MM-DD, you can use a self join:
SELECT *
FROM events e1 INNER JOIN events e2
ON e2.event > e1.event
AND datetime(e2.date || ' ' || e2.time, e2.duration || ' second') > e1.date || ' ' || e1.time
AND e2.date || ' ' || e2.time < datetime(e1.date || ' ' || e1.time, e1.duration || ' second');
See the demo.

Maybe, supposing you have index on date-time
SELECT *
FROM events e1 INNER JOIN events e2
ON datetime(e2.date || ' ' || e2.time)
BETWEEN (e1.date || ' ' || e1.time)
AND datetime(e1.date || ' ' || e1.time, e1.duration || ' second')
WHERE e2.event <> e1.event;
As #forpas says, if you kept date an time values in a single column, and have index on this column, performance will be better

Related

How to use MAX() for multiple dates in SQLite?

My goal is to choose the PTID with the most recent date with its recent time. I was trying to use the MAX() function to choose the most recent date with its recent time but received an error syntax (see the double asterisk on Line 9 in my code). Is there a statement to do that or would it be easier to do it in Python? I appreciate all the help!
Table 1
PTID
RESULT_DATE1
RESULT_TIME
DIAGNOSIS_CD
54
2020-01-06
10:03:02
W34
54
2020-01-01
09:18:05
S38
54
2020-01-01
03:08:45
V98
54
2020-04-04
02:09:08
V98
54
2020-04-04
12:12:34
V89
My Goal:
PTID
RESULT_DATE1
RESULT_TIME
DIAGNOSIS_CD
54
2020-04-04
12:12:34
V98
54
2020-01-06
10:03:02
W34
54
2020-01-01
09:18:05
S38
My Code:
CREATE TABLE covid AS
SELECT t1.*, t2.*
FROM lab9 t1 JOIN diagnosis9 t2 ON t2.PTID = t1.PTID
AND t1.RESULT_DATE1 || ' ' || t1.RESULT_TIME
BETWEEN
date(t2.diagdate1, '-7 day') || ' ' || t2.DIAG_TIME
AND
t2.diagdate1 || ' ' || t2.DIAG_TIME
**WHERE RESULT_DATE1 = MAX(RESULT_DATE1)**
GROUP BY t1.PTID || DIAGNOSIS_CD
ORDER BY t1.PTID;
First, you should not group by the concatenation of 2 columns because this may lead to unexpected results.
You should group by the 2 columns.
Also, you can't use an aggregate function like MAX() in the WHERE clause of a query.
What you need is the max value of the expression t1.RESULT_DATE1 || ' ' || t1.RESULT_TIME which you can finally split to date and time with the functions date() and time():
CREATE TABLE covid AS
SELECT t1.PTID,
date(MAX(t1.RESULT_DATE1 || ' ' || t1.RESULT_TIME)) RESULT_DATE1,
time(MAX(t1.RESULT_DATE1 || ' ' || t1.RESULT_TIME)) RESULT_TIME,
t2.*
FROM lab9 t1 JOIN diagnosis9 t2
ON t2.PTID = t1.PTID
AND t1.RESULT_DATE1 || ' ' || t1.RESULT_TIME
BETWEEN
date(t2.diagdate1, '-7 day') || ' ' || t2.DIAG_TIME AND t2.diagdate1 || ' ' || t2.DIAG_TIME
GROUP BY t1.PTID, t2.DIAGNOSIS_CD
ORDER BY t1.PTID;
The above query will return the rows with the max datetime for each combination of PTID and DIAGNOSIS_CD with the use if SQLite's feature of bare columns.

Query Items which were resold within 1 year of last selling date

I have a table with details of sold cars. Some of these cars have been resold within last 1, 2 or 3 years. The table looks like this:
Car_Type || Car_Reg_No || Sold_Date || Listing_No
Hatch || 23789 || 2017-02-03 11:26 || X6529
Coupe || 16723 || 2016-11-07 09:40 || N8156
Sedan || 35216 || 2016-05-23 10:34 || M8164
Hatch || 23789 || 2016-09-16 04:30 || O7361
Now, I need to query records (cars) which were re-sold within 1 year of their latest sold date and how many times were they sold. So, my output would be like this:
Car_Type || Car_Reg_No || Sold_Count || Latest_Sold_Date
Hatch || 23789 || 2 || 2017-02-03 11:26
In essence, How do I check for re-sold records within a specific time frame of their latest sold date?
You can do this by finding the max, and joining based on your conditions.
declare #TableA table (Car_Type varchar(64)
,Car_Reg_No int
,Sold_Date datetime
,Listing_No varchar(6))
insert into #TableA
values
insert into #TableA
values
('Hatch',23789,'2017-02-03 11:26','X6529'),
('Coupe',16723,'2017-11-07 09:40','N8156'),
('Sedan',35216,'2017-05-23 10:34','M8164'),
('Hatch',23789,'2016-09-16 04:30','O7361'),
('Coupe',16723,'2014-11-07 09:40','N8156')
;with cte as(
select
Car_Type
,Car_Reg_No
,Latest_Sold_Date = max(Sold_Date)
from
#TableA
group by
Car_Type
,Car_Reg_No)
select
a.Car_Type
,a.Car_Reg_No
,Sold_Count = count(b.Listing_No) + 1
,a.Latest_Sold_Date
from cte a
inner join
#TableA b on
b.Car_Reg_No = a.Car_Reg_No
and b.Sold_Date != a.Latest_Sold_Date
and datediff(day,b.Sold_Date,a.Latest_Sold_Date) < 366
--if you want only cars which were sold within last year too, uncomment this
--and datediff(day,a.Latest_Sold_Date,getdate()) < 366
group by
a.Car_Type
,a.Car_Reg_No
,a.Latest_Sold_Date
By my understanding..,
select sd1.Car_Type, sd1.Car_Reg_No,
count(sd1.Car_Reg_No) + 1 'no of sales in last one year', --1 is added because, see the last condition
sd1.Sold_Date 'Last sold date'
from(
select *,ROW_NUMBER() over(partition by Car_Reg_No order by sold_date desc) as rn from #Table) as sd1
join
(select * from #Table) as sd2
on sd1.Car_Type = sd2.Car_Type
and DATEDIFF(dd,sd2.Sold_Date,sd1.Sold_Date) < 366
and sd1.rn = 1
and sd1.Sold_Date <> sd2.Sold_Date -- here last sold is eliminated. so count is added by one.
group by sd1.Car_Type,sd1.Sold_Date, sd1.Car_Reg_No
order by sd1.Car_Reg_No

Show a Total for a SQL Table

I am trying to add a Total line at the bottom of this sql syntax but thus far have received no break through. I have viewed the following but both of them do not adhere with my condition. Can someone please provide assistance with regards to this.
Add a summary row with totals
Adding a total row to the end of query result
select dm.Builder ||' ('|| dm.Lot_Size || '''s)' as"Builder",count(sd.Address) "The Count",
dm."Construction_ID"
from input dm
left join data sd on sd.inputfk = dm.inputpk
and sd.Closing Date >= DATE '01/01/2017' and sd.Closing Date < DATE '06/30/2017'
where dm.Construction_ID = 'AJR'
group by dm.Builder,dm.Lot_Size, dm.Project_ID
having count(sd.Address) > 0
order by dm.Builder
When I run it:
Builder The Count Construction_ID
Jake's Homes (55's) 2 AJR
Jake's Homes (65's) 3 AJR
Maggie's Homes (65's) 5 AJR
Maggie's Homes (66's) 2 AJR
Maggie's Homes (75's) 3 AJR
Maggie's Homes (90's) 1 AJR
Total ----------> 16
Your group by has dm.Project_ID, sd.Address which is probably causing it.
For total, you can use ROLLUP:
Try this:
select coalesce(dm.Builder || ' (' || dm.Lot_Size || '''s)', 'Total') as "Builder",
count(sd.Address) "The Count",
dm."Construction_ID"
from input dm
left join data sd on sd.inputfk = dm.inputpk
and sd.Closing date >= date '01/01/2017'
and sd.Closing date < date '06/30/2017'
where dm.Construction_ID = 'AJR'
group by rollup(dm.Builder || ' (' || dm.Lot_Size || '''s)')
having count(sd.Address) > 0
order by "Builder"
Try this:
select dm.Builder ||' ('|| dm.Lot_Size || '''s)' as"Builder",count(sd.Address) "The Count",
dm."Construction_ID"
from input dm
left join data sd on sd.inputfk = dm.inputpk
and sd.Closing Date >= DATE '01/01/2017' and sd.Closing Date < DATE '06/30/2017'
where dm.Construction_ID = 'AJR'
group by rollup( (dm.Builder,dm.Lot_Size, dm.Project_ID) )
having count(sd.Address) > 0
order by dm.Builder
Just... why you need count(sd.Address) > 0 ?
Given the post is tagged with postgresql, assuming it is for that platform; as such, see https://www.postgresql.org/docs/9.5/static/queries-table-expressions.html#QUERIES-GROUPING-SETS

Concatenation of max_times within 15 minute time intervals SQL

I am trying to write a sql query that pulls an ID and concatenates the max times within 15 minute time intervals starting from the first time.
i.e. for one log_id data might be
101 01:01
101 01:08
101 01:23
101 02:01
101 02:10
101 02:16
we would want to display
101 01:01, 01:08, 01:23, 2:01, 2:16
any ideas?
here is the starting query we are using:
select
ol.log_id,
ifm.meas_value,
ifm.measure_id,
ifm.recorded_time
from meas ifm
inner join rec ifr on ifm.fsd_id = ifr.fsd_id
inner join pe on ifr.data_id = pe.data_id
inner join record_summary f on pe.n_id = f.n_id
inner join pe2 on pe.t_id = pe2.t_id and pe.date = pe2.date and pe2.type = 51
inner join log l on pe2.ata_id = l.data_id and l.date = pe2.date
where ifm.measure_id in ('891')
and ol.date >= trunc(sysdate - 3)
for each log_id there will be multiple recorded times we want to pull the first time, and the maximum time in every 15 minute interval until the last time. These times will be concatenated to a list.
We tried a listagg with all the values, but there are too many times so the end-user wants to only see one value for every 15 minutes.
Basically you have 3 questions in one:
How to round date field to 15 min?
https://community.oracle.com/thread/1042863
ceil(to_number(to_char(test_timestamp, 'yyyymmddhh24mi'))/15) * 15
How to get the row from a group?
That is a very popular question, you will find something here:
https://stackoverflow.com/questions/tagged/oracle+greatest-n-per-group?sort=votes&pageSize=30
How to aggregate over string values to concatenate within a group:
LISTAGG(convertedTimeField, ' ')
Try to combine all three pieces in one query to get required result.
To simplify working with the following table:
CREATE TABLE Test ( id NUMBER, log DATE );
(Note: DATE in oracle is actually dateTime. String concatenation is done with ||.)
Your given list seems to indicate, that when the max and the min is the same you only display it once, this can be done by grouping twice:
SELECT
O.id,
O.logDate,
LISTAGG(O.logTimes, ', ') WITHIN GROUP (ORDER BY O.logTimes) logTimes
FROM (
SELECT
O.id,
O.logDate,
O.G G,
CASE
WHEN TO_CHAR(MIN(O.log), 'HH24:MI') <> TO_CHAR(MAX(O.log), 'HH24:MI') THEN
TO_CHAR(MIN(O.log), 'HH24:MI') || ', ' || TO_CHAR(MAX(O.log), 'HH24:MI')
ELSE
TO_CHAR(MIN(O.log), 'HH24:MI')
END logTimes
FROM (
SELECT
T.id,
T.log,
TRUNC(T.log) logDate,
TO_CHAR(T.log, 'HH24') || FLOOR(TO_NUMBER(TO_CHAR(T.log, 'MI')) / 15) G
FROM
Test T
) O
GROUP BY
O.id, O.logDate, O.G
) O
GROUP BY
O.id, O.logDate
;
See SQL fiddle.

Sum and distinct dont alter results?

I am a novice trying to work through this here with no luck so far, any help is greatly appreciated!!!
Select Distinct
(AB.agency_no || '-' || ab.branch_no) AS "AGENCY-BRANCH",
count (AB.agency_no || '-' || ab.branch_no) AS Occurences,
A.AGY_NAME AS AGENCY,
Sum(AB.annual_premium) as Premium
From Agency_Book_View AB, Agency A, Branch B
Where AB.agency_no = A.Agency_No
AND B.EXPIRATION_DATE = TO_DATE('12-31-2078', 'MM-DD-YYYY')
AND B.EFFECTIVE_DATE <= sysdate and b.effective_date >=sysdate - 364
Group by AB.agency_no || '-' || ab.branch_no, A.Agy_Name, ab.annual_premium
Order by AB.agency_no || '-' || ab.branch_no
So I am trying to return total annual premium per "agency-branch" and I am getting multiple occurrences of agency-branch. I am trying to get one line per agency branch. I hope this is clear. I tried to include a result set but wasnt allowed to include a picture in my post.
Thanks very much!
Brad
Try this :
SELECT (AB.agency_no || '-' || AB.branch_no) AS "AGENCY-BRANCH",
COUNT(AB.agency_no || '-' || AB.branch_no) AS Occurences,
A.AGY_NAME AS AGENCY,
SUM(AB.annual_premium) AS Premium
FROM Agency_Book_View AB, Agency A, Branch B
WHERE AB.agency_no = A.Agency_No AND AB.branch_no = B.branch_no
AND B.EXPIRATION_DATE = TO_DATE('12-31-2078', 'MM-DD-YYYY')
AND B.EFFECTIVE_DATE <= SYSDATE AND B.effective_date >= SYSDATE - 364
GROUP BY AB.agency_no || '-' || AB.branch_no, A.Agy_Name
ORDER BY AB.agency_no || '-' || AB.branch_no
I joined B table and AB table, removed the DISTINCT and the GROUPed BY ab.annual_premium.
I think you need to remove ab.annual_premium from the group by clause.