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

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.

Related

selecting values in same time period sqlite

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

How to compare the timestamp of the exact hours/minute/seconds?

I have to columns:
BEFORE_TIME & AFTER_TIME
2021-09-02 09:41:00.000 || 2021-09-09 09:41:00.000
2021-09-03 09:09:07.000 || 2021-09-10 09:09:07.000
2021-09-03 13:45:48.000 || 2021-09-10 15:45:48.000
I want to compare the hours/minutes and seconds to see if they match. I can ignore the years/months and days. Is there a way I can do this?
For example, in the above, I know the first two records match since the have the same hours, minutes and seconds in both columns, but the last record does not match.
You can use trunc() to truncate the timestamp to seconds, and cast to ::time to remove the date part:
select a=b
, trunc(a::time, 'second') = trunc(b::time, 'second')
from (
select '2021-01-01 10:10:10.313'::timestamp a
, '2021-08-01 10:10:10.444'::timestamp b
)
(Which gives false and true)
Snowflake provides HOUR(), MINUTE() and SECOND() functions:
https://docs.snowflake.com/en/sql-reference/functions/hour-minute-second.html
WITH t AS (
SELECT
'2021-09-02 09:41:00.000'::timestamp as before_time,
'2021-09-09 09:41:00.000'::timestamp as after_time
UNION
SELECT
'2021-09-03 09:09:07.000'::timestamp as before_time,
'2021-09-10 09:09:07.000'::timestamp as after_time
UNION
SELECT
'2021-09-03 13:45:48.000'::timestamp as before_time,
'2021-09-10 15:45:48.000'::timestamp as after_time
)
SELECT
hour(before_time) = hour(after_time)
and minute(before_time) = minute(after_time)
and second(before_time) = second(before_time) as time_check
FROM
t;
Or you can put it inside a UDF:
CREATE OR REPLACE FUNCTION time_check (
BEFORE_TIME timestamp,
AFTER_TIME timestamp
)
returns boolean
LANGUAGE JAVASCRIPT
as
$$
// do some validation here
var before = new Date(BEFORE_TIME);
var after = new Date(AFTER_TIME);
return before.getSeconds() == after.getSeconds() &&
before.getMinutes() == after.getMinutes() &&
before.getHours() == after.getHours();
$$
;
WITH t AS (
SELECT
'2021-09-02 09:41:00.000'::timestamp as before_time,
'2021-09-09 09:41:00.000'::timestamp as after_time
UNION
SELECT
'2021-09-03 09:09:07.000'::timestamp as before_time,
'2021-09-10 09:09:07.000'::timestamp as after_time
UNION
SELECT
'2021-09-03 13:45:48.000'::timestamp as before_time,
'2021-09-10 15:45:48.000'::timestamp as after_time
)
SELECT
time_check(before_time, after_time) as time_check
FROM
t;
Both of above should return:
+------------+
| TIME_CHECK |
|------------|
| True |
| True |
| False |
+------------+

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

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.