Syntax error on sqlite when updating table - sqlite

I'm pulling data from my energy provider as a rawTable and then would like to perform some calculations to place the data in an easier way to search as well as to do calculations.
The data I receive from the energy supplier lands in this table:
CREATE TABLE "rawData" (
"ID" INTEGER NOT NULL,
"consumption" REAL NOT NULL,
"startTime" TEXT NOT NULL,
"endTime" TEXT NOT NULL,
PRIMARY KEY("ID" AUTOINCREMENT)
);
I then created this table to hold the data I want per day.
CREATE TABLE "structuredData" (
"rowID" INTEGER NOT NULL,
"Year" INTEGER NOT NULL,
"Month" INTEGER NOT NULL,
"Day" INTEGER NOT NULL,
"PeakConsumption" REAL,
"OffPeakConsumptioon" REAL,
PRIMARY KEY("rowID" AUTOINCREMENT)
);
To get the offpeak consumption from the rawData, I run the following query:
INSERT INTO structuredData (Year, Month, Day, OffPeakConsumptioon)
SELECT strftime('%d', startTime) as valDay,
strftime('%m', startTime) as valMonth,
strftime('%Y', startTime) as valYear,
SUM(consumption) as valTotalDay
FROM rawData
WHERE
strftime('%Y', startTime)>='2021'
AND (strftime('%H:%M:%S',startTime) >= "00:30:00"
AND strftime('%H:%M:%S',startTime) < "04:30:00")
GROUP BY valYear, valMonth, valDay ;
Then I need to essentially do the same to the Peak Consumption and came up with this query:
UPDATE structuredData
SET PeakConsumption = daily.amt
FROM (SELECT SUM(consumption) as amt, strftime('%d', startTime) as valDay, strftime('%m', startTime) as valMonth, strftime('%Y', startTime) as valYear
FROM rawData
WHERE strftime('%Y', startTime)>='2021'
AND (strftime('%H:%M:%S',startTime) >= "00:00:00" AND strftime('%H:%M:%S',endTime) <= "00:30:00"
OR strftime('%H:%M:%S',startTime) >= "04:30:00" AND strftime('%H:%M:%S',endTime) <="23:30:00")
GROUP BY valYear, valMonth, valDay) AS daily
WHERE structuredData.Day = daily.valDay
and structuredData.Month = daily.valMonth
and structuredData.Year = daily.valYear;
However, this tells me there's an error.
Execution finished with errors.
Result: near "FROM": syntax error
At line 1:
UPDATE structuredData
SET PeakConsumption = 1
FROM
Any ideas where I may be messing up??

Related

Sqlite select a record inserted or updated in last 5 minutes

I am trying to select any record that has been inserted or updated for the last five minutes in a sqlite3 data table where the date column updated_at is in format YYYY-MM-DD HH:MM:SS:
CREATE TABLE IF NOT EXISTS emp_tb(
emp_id INTEGER PRIMARY KEY NOT NULL,
emp_names TEXT NOT NULL,
emp_number TEXT NOT NULL UNIQUE,
ent_id INTEGER NOT NULL,
active INTEGER NOT NULL DEFAULT "0",
updated_at TEXT NULL DEFAULT (datetime('now', 'localtime')),
syncstatus INTEGER NOT NULL DEFAULT "0")
I have tried the following, but it returns either any record for the current day not necessarily updated in last 5 minutes or none at all:
SELECT emp_id, emp_names FROM emp_tb WHERE ent_id = ? \
AND date(updated_at) = date('now') AND time(updated_at) >= time('now','-5 minutes')
SELECT emp_id, emp_names FROM emp_tb WHERE ent_id = ? \
AND datetime(updated_at) >= datetime('now','-5 minutes')
SELECT emp_id, emp_names FROM emp_tb WHERE ent_id = ? \
AND updated_at >= datetime('now','-5 minutes')
I know how to do it in Mysql but how do you query time for a record updated or inserted in the last five minutes in Sqlite3?
The column updated_at has the proper format, so there is no need to use the function datetime() for its values.
Your last query should work, but maybe there is a timezone problem, so use also 'localtime':
SELECT emp_id, emp_names
FROM emp_tb
WHERE ent_id = ?
AND updated_at >= datetime('now', '-5 minutes', 'localtime')

Why is my JulianDay returning null when trying to get number of days between two dates

Hi I am trying to get the number of days between two dates in one of my tables arrivaldate and departuredate however i dont know why my JulianDay is returning null value.
Select Cast ((
JulianDay(datetime(departuredate)) - JulianDay(datetime(arrivaldate))) As Integer)
from booking;
My table
CREATE table Booking(
BookingID INTEGER PRIMARY KEY autoincrement,
BCustomerID INTEGER NOT NULL,
arrivaldate VARCHAR(10) NULL,
departuredate VARCHAR(10) NULL,
paymentmethod VARCHAR (45)NULL,
RoomType VARCHAR (20)
);
INSERT INTO Booking(BCustomerID,arrivaldate,departuredate,paymentmethod,RoomType) VALUES
(1,'2018/07/02','2018-07-10','Card','Single'),
(2,'2018/07/12','2018-07-18','Cash','Double'),
(3,'2018/07/12','2018-07-19','Cash','Single'),
(4,'2018/07/06','2018-07-07','Card','Double'),
(5,'2018/08/14','2018-08-24','Card','Triple'),
(6,'2018/09/01','2018-09-04','Cash', 'Quad');
SQLite's datetime functions like datetime() and julianday() work only for dates in the format 'YYYY-MM-DD' or datetimes in the format 'YYYY-MM-DD hh:mm:ss.sss'.
Your dates contain '/' instead of '-' (only in arrivaldate or departuredate too?).
Use the function replace():
SELECT CAST (
julianDay(REPLACE(departuredate, '/', '-')) -
julianDay(REPLACE(arrivaldate, '/', '-'))
AS integer
) AS days
FROM booking;
Or better update the table so your dates have the proper for SQLite format:
UPDATE booking
SET arrivaldate = REPLACE(arrivaldate, '/', '-'),
departuredate= REPLACE(departuredate, '/', '-')
and then you can do:
SELECT CAST(julianDay(departuredate) - julianDay(arrivaldate) AS integer) AS days
FROM booking;
See the demo.

SQLite: trigger to check newly inserted row against limits in another table

I have a database with the following schema:
Sensors (
ID INTEGER PRIMARY KEY AUTOINCREMENT
UNIQUE
NOT NULL,
SITE_ID INTEGER REFERENCES Sites (ID)
NOT NULL,
NAME TEXT UNIQUE
NOT NULL
);
Sites (
ID INTEGER PRIMARY KEY AUTOINCREMENT
UNIQUE
NOT NULL,
NAME TEXT UNIQUE
NOT NULL
);
Data (
SENSOR_ID INTEGER REFERENCES Sensors (ID)
NOT NULL,
COUNT INTEGER NOT NULL,
TIME DATETIME NOT NULL,
TYPE TEXT NOT NULL,
VALUE REAL NOT NULL,
PRIMARY KEY (
SENSOR_ID,
COUNT,
TIME,
TYPE
)
);
Limits (
SITE_ID INTEGER REFERENCES Sites (ID)
NOT NULL,
TYPE TEXT NOT NULL,
HIGH REAL NOT NULL,
LOW REAL NOT NULL,
PRIMARY KEY (
SITE_ID,
TYPE
)
);
Data contains all the data for all sensors and sites, Data has a few different types. The limits have a row for each type of data for each of the sites. I want to create a table identical to Data (called Warnings) containing only the rows where the value lies outside of the limits in Limit.
I want to do this with a trigger because the limits can change and the rows are added to data sporadically.
Here's my best attempt so far:
CREATE TRIGGER VALUE_OUT_OF_RANGE
AFTER INSERT
ON Data
WHEN NEW.VALUE < (SELECT Limits.LOW FROM Limits INNER JOIN Sensors ON (Sensors.SITE_ID = Limits.SITE_ID) WHERE (Sensors.ID = NEW.SENSOR_ID AND Limits.TYPE = NEW.TYPE))
BEGIN
INSERT INTO Warnings(SENSOR_ID, COUNT, TIME, TYPE, VALUE) VALUES(NEW.SENSOR_ID, NEW.COUNT, NEW.TIME, NEW.TYPE, NEW.VALUE);
END;
In my attempt I've only checked against the lower limit, in the final trigger I would like to check that the value is between the LOW and HIGH limits.
I've tried the Select statement seperately and I get the data that I am looking for.
Any help or suggestion is greatly appreciated.
I managed to find a solution that works.
Posting it in case it helps anyone.
CREATE TRIGGER VALUE_OUT_OF_RANGE
AFTER INSERT
ON Data
FOR EACH ROW
WHEN NEW.VALUE < (
SELECT Limits.LOW
FROM Limits
JOIN
Sensors ON (Sensors.SITE_ID = Limits.SITE_ID)
WHERE (Sensors.ID = NEW.Sensor_ID AND
Limits.TYPE = NEW.TYPE)
LIMIT 1
)
OR
NEW.VALUE > (
SELECT Limits.HIGH
FROM Limits
JOIN
Sensors ON (Sensors.SITE_ID = Limits.SITE_ID)
WHERE (Sensors.ID = NEW.Sensor_ID AND
Limits.TYPE = NEW.TYPE)
LIMIT 1
)
BEGIN
INSERT INTO Warnings (
SENSOR_ID,
COUNT,
TIME,
TYPE,
VALUE
)
VALUES (
NEW.SENSOR_ID,
NEW.COUNT,
NEW.TIME,
NEW.TYPE,
NEW.VALUE
);
END;

To INSERT values from CTE result

I have 'SchoolYearStartEnd' table
CREATE TABLE SchoolYearStartEnd (
id INT PRIMARY KEY UNIQUE,
StartDate DATE,
EndDate DATE
);
and the second 'SchoolYearsTeachingDays' table
CREATE TABLE SchoolYearsTeachingDays (
aDate DATE PRIMARY KEY UNIQUE
);
which I want to fill out with dates from a CTE like this:
WITH RECURSIVE dates(x) AS (
SELECT (SELECT StartDate FROM SchoolYearStartEnd)
UNION ALL
SELECT DATE(x, '+1 DAYS') FROM dates WHERE x < (SELECT EndDate FROM SchoolYearStartEnd)
)
SELECT * FROM dates WHERE CAST(STRFTIME('%w',x) AS INTEGER) > 0
;
I tried with this code here:
INSERT INTO SchoolYearsTeachingDays (aDate) VALUES (
WITH RECURSIVE dates(x) AS (
SELECT (SELECT StartDate FROM SchoolYearStartEnd)
UNION ALL
SELECT DATE(x, '+1 DAYS') FROM dates WHERE x < (SELECT EndDate FROM SchoolYearStartEnd)
)
SELECT * FROM dates WHERE CAST(STRFTIME('%w',x) AS INTEGER) > 0 -- To exclude Sundays.
;
);
but without success. I get these errors:
Error: near "RECURSIVE": syntax error
Error: near ")": syntax error
So what am I missing here?
Best, Pal
When you are inserting from a SELECT query, you must not use VALUES:
INSERT INTO SchoolYearsTeachingDays (aDate)
WITH RECURSIVE dates(x) AS (...)
SELECT * FROM dates ...;

Return 0 if the date for a certain day does not have values

I'm doing a query to return the number of count records for a certain date.
The problem is when I use the GroupBy by a certain day, If the date have no records then the date for that day will not be shown in the output.
How can I achieve that?
I'm doing something like:
SELECT COUNT(History.Id)
FROM History
INNER JOIN User ON User.Id = History.UserId
WHERE (#StartDate = #NullDate OR History.CreatedOnDate >= #StartDate)
AND (#EndDate = #NullDate OR History.CreatedOnDate <= #EndDate)
GROUP BY History.CreatedOnDat
Example
01-08, 3 records
02-08, 2 records
04-08, 5 records
I need to have 03-08 with 0 records.
Create a temp table with one day per row:
Declare #StartDate datetime = '2016-08-01'
Declare #EndDate datetime = '2016-08-31'
declare #temp table
(
oneday datetime
);
WHILE #StartDate <= #EndDate
begin
INSERT INTO #temp VALUES (#StartDate);
SET #StartDate = Dateadd(Day,1, #StartDate);
end
select * from #temp
Then, simply join your query with this temp table.

Resources