How to make the database delete a row after certain time on the row? - sql

I'm doing a project about reporting situations on a map. Each report is marked by a pin on the map. The pin table has an attribute, report_time, that saves the hour in which the pin was inserted (or in which the report was made).
How can I make a function/trigger/procedure (whatever is the best option) to delete that row after 15 minutes since the report? I want something on my database that gets the report_time and deletes the row if 15 minutes have passed.

Instead of constantly deleting rows, how about just using a view?
create view v_pin as
select p.*
from pin p
where p.report_time > now() - interval '15 minute;
Anyone who uses the view will only see the most recent rows.
Then, when the database is quiescent or when you want -- say once an hour or once a day or once a week, just schedule a job to remove old rows:
delete from pin
where report_time < now() - interval '15 minute';
What is elegant about this solution is that users will never see inappropriate rows in the table, even if the job does not run as scheduled or the table is locked for updates for some reason.

Related

Firebird time-sequence data with gaps

I'm using Firebird 2.5 through Delphi 10.2/FireDAC. I have a table of historical data from industrial devices, one row per device at one-minute intervals. I need to be able to retrieve an arbitrary time window of records on an arbitrary interval span (every minute, every 3 minutes, every 15 minutes, etc.) which then gets used to generate a trending grid display or a report. This example query, pulling every 3 minutes records for a two-day window for 2 devices, does most of what I need:
select *
from avc_history
where (avcid in (11,12))
and (tstamp >= '6/26/2022') and (tstamp < '6/27/2022')
and (mod(extract(minute from tstamp), 3) = 0)
order by tstamp, avcid;
The problem with this is that, if device #11 has no rows for a part of the time span, then there is a mismatch in the number of rows returned for each device. I need to return a row for each device on each minutes period regardless of whether a row on that timestamp actually exists in the table - the other fields of the row can be null as long as the tstamp field has the timestamp and the avcid field has the device's ID.
I can fix this up in code, but that's a memory and time hog, so I want to avoid that if possible. Is there a way to structure a query (or if necessary, a stored procedure) to do what I need? Would some capability in the FireDAC library that I'm not aware of make this easier?

Split date_start and date_end by hours on Metabase

I have table with a column "Begin At" and another column "End At" that represent when a task begin and when a task end i would want to have a Bar display which display the cuantity of tasks that are being done in a specific hour along an interval of time.
For example, from the following table
I would want to be able to see that from 07/12/2021 21:00 to 07/12/2021 22:00 there were 3 tasks being done (row 1, row 2, row 3).
And also as i will have several thousands of rows i would want to use the date widget from metabase in order to specify range of times.
I have been struggling with this from the last week, i tried to create auxiliar questions where to query after but finally my only succeed was to hard code the 24 hours from a day but then i was not able to use the time widget and i needed to specify the dates myself on the sql each time i want to check a specific day and also i only was able to check from 24 to 24 hours, not from for example 02/12/2021 6:00 to 04/12/2021 18:00
My metabase is running on a PostgreSQL database. Is this even possible on Metabase? If not what are your advices to build this? Other plaforms? Pure SQL? Python?
Thank you so much
I am not sure about metabase but from a PostgreSQL point of view this calls for the use of range-types, specifically the tsrange/tstzrange, depending on whether you have time zone information or not.
So a query could be:
SELECT
*
FROM "someTable"
WHERE
tsrange("Begin At", "End At", '[)')
&&
tsrange('02/12/2021 6:00', '04/12/2021 18:00', '[)')
However I don't know how you would get the '02/12/2021 6:00' and '04/12/2021 18:00' out of your metabase user-interface.

How to add a minutes column to date column sql

I may sound silly asking it - but I have the need to add a value derived from one column of database to the other which is the date.
Following is the image of data I have - timeelapsed/60000 gives me the duration of task in minutes and I would require the same to be deducted from the lastupdatedtime to know the time when was the task picked. Please help!
I have attempted as per your suggestion
lastupdatedtime - (timeelapsed/60000) * interval '1 minute' as task_pick_datetime,
But I see the difference appearing is huge.
For instance, the audited time is 2020-03-12 17:41:39.224, duration in min is 3.06 but the task pick time shows 2020-03-12 12:08:35.417 which is 5 hours difference. Unsure where am I going wrong.
enter image description here
In Standard SQL (which is the tag on your question), you can use:
select lastupdatetime - (timeelapsed/60000) * interval '1 minute' as task_pick_datetime
However, date/time functions are notoriously database dependent, so your database may not support this syntax.

How do I check whether the time has reached the next half hour in SQL?

I know, confusing title. Let me explain:
I have a job that has multiple steps.
The job runs every 15 minutes.
One of the steps in the job is to run a check (stored procedure) to see if there are records in a temp table that is created inside that stored procedure.
If there are records, I want to send an email.
The email can only be sent between 7am and 4pm and it'll repeat every 30 minutes.
Right now, I know how to check whether something exists and it's in the right time frame:
IF (EXISTS ( SELECT 1
FROM #NewItems
WHERE DATEPART(HOUR, GETDATE()) BETWEEN 7 AND 16 ))
BEGIN
-- send email
END
So my question is, how do I do the above check AND it's the next half hour?
For example, I want to send this email at 7am, 7:30am, 8am, 8:30am, etc. until 16:00 (or 4pm).
How would I go about doing this?
You could use an audit table to keep track of the emails that you've sent. Something like:
CREATE TABLE EMAIL_AUDIT_TRAIL
(
EMAIL_SEND_TIME AS DATETIME NOT NULL,
EMAIL_SUMMARY AS VARCHAR(100)
)
A benefit of this is that you get some traceability on the server side to say when emails were sent, and maybe a short summary of what they said (like number of items or whatever).
Each time the stored procedure runs, you could round the current time to the last 30 minute interval using something like CAST(FLOOR(CAST(GETDATE() as FLOAT(53))*48)/(48) AS DATETIME) (adapted from an answer on the question T-SQL: Round to nearest 15 minute interval), and then check to see if that interval has an entry in the audit table.
If it does not, send the email (and add the appropriate entry to the audit table).
You could even use the same approach to determine if the interval was one that should have an email sent by checking whether the current time (rounded to the nearest 30 minutes) is contained within a table containing all of the times during the day that should have emails sent (so in your case, all 30 minute intervals between 7:00 and 16:00).
Obviously you'd have to include some cleanup of the audit table to make sure it doesn't grow forever as well.

Select rows whose IDs are not found in another table under certain constraints

The practical problem I'm solving is to display a list of items that have been updated recently that the user has not viewed recently.
I'm trying to return a table containing items that are not containing in an item views table for a given user (let's say for this case user number 1). I've come up with:
SELECT * FROM items i
WHERE i.updated_at > date_sub(curdate(), interval 10 day)
AND i.id NOT IN (
SELECT item_id FROM item_views v
WHERE i.created_at > date_sub(curdate(), interval 10 day)
AND i.user_id = 1
)
This seems to work fine (is it even the best way to do it?). However, I run into issues when considering an item that was viewed 8 days ago and updated 3 days ago. Such an item is clearly new, but it wouldn't show up under this query. How should I approach adding this restriction?
If you have the updated_at column in your view you could always add a line to check to make sure the updated date is not within your timeline. Better yet you could check to make sure your updated date is greater than your last viewed date.
This is not optimal solution. But fast anwser replace the AND with OR should work.