I am new to SQL. I am using PostgreSQL. I have created the stored function called report:
CREATE OR REPLACE FUNCTION report(sensors VARCHAR,fromdate DATE,todate DATE)
RETURNS TABLE (
sensor VARCHAR,
id INT,
value INT,
created_date DATE
)
AS $$
DECLARE
var_r record;
BEGIN
FOR var_r IN(SELECT
*
FROM probe_data
WHERE probe_data.sensor =sensors AND probe_data.created_date >= fromdate AND probe_data.created_date <= todate )
LOOP
sensor := var_r.sensor ;
id := var_r.id;
created_date := var_r.created_date;
value:= var_r.value;
RETURN NEXT;
END LOOP;
END;
I want to get the data's between two date ranges.When I execute in SQL tool, it returns my desired output. But when I call the function
let sql= `select * from public.report($1,$2,$3);`
let values=[req.body.sensors,req.body.fromdates,req.body.todates];
from my nodejs program, I am getting the data's out of range.
Here is my screen shot:
This is the structure of my return table
As you can see,In my second screen shot, I'm getting the data out of range. I don't where I am doing wrong.
Your parameter is declared as DATE but you are trying to pass a timestamp. So Postgres will cast the passed value to a date and you lose the time information. You need to define the parameter as timestamp if you want it to be treated as one. The return type of created_at should probably be a timestamp as well.
You can also get rid of the CURSOR loop and PL/pgSQL as well:
CREATE OR REPLACE FUNCTION report(sensors VARCHAR, fromdate timestamp, todate timestamp)
RETURNS TABLE (sensor VARCHAR, id INT, value INT, created_date timestamp)
AS $$
select pb.sensor, pb.id, pb.value, pg.created_date
FROM probe_data
WHERE pb.sensor = sensors
AND pb.created_date >= fromdate
AND pb.created_date <= todate;
$$
language sql;
Related
I'm wondering if it's possible to concatenate PLyResults somehow inside a function. For example, let's say that firstly I have a function _get_data that, given a tuple (id, index) returns a table of values:
CREATE OR REPLACE FUNCTION _get_data(id bigint, index bigint):
RETURNS TABLE(oid bigint, id bigint, val double precision) AS
$BODY$
#...process for fetching the data, irrelevant for the question.
return recs
$BODY$
LANGUAGE plpython3u;
Now I would like to be able to create a generic function defined as such, that fetches data between two boundaries for a given ID, and uses the previous function to fetch data individually and then aggregate the results somehow:
CREATE OR REPLACE FUNCTION get_data(id bigint, lbound bigint, ubound bigint)
RETURNS TABLE(oid bigint, id bigint, val double precision) AS
$BODY$
concatenated_recs = [] #<-- For the sake of argument.
plan = plpy.prepare("SELECT oid, id, val FROM _get_data($1, $2);", ['bigint', 'bigint'])
for i in range(lbound, ubound+1):
recs = plpy.execute(plan, [id, i]) # <-- Records fetched individually
concatenated_recs += [recs] #<-- Not sure how to concatenate them...
return concatenated_recs
$BODY$
LANGUAGE plpython3u;
Perhaps I am missing something, but the answer you gave looks like a slower, more complicated version of this query:
SELECT oid, id, val
FROM generate_series(your_lower_bound, your_upper_bound) AS g(i),
_get_data(your_id, i);
You could put that in a simple SQL function with no loops or temporary tables:
CREATE OR REPLACE FUNCTION get_data(id bigint, lbound bigint, ubound bigint)
RETURNS TABLE(oid bigint, id bigint, val double precision) AS
$BODY$
SELECT oid, id, val
FROM generate_series(lbound, ubound) AS g(i),
_get_data(id, i);
$BODY$ LANGUAGE SQL;
Although I wasn't able to find a way to concatenate the results from the PL/Python documentation, and as of 06-2019, I'm not sure if the language supports this resource, I could solve it by creating a temp table, inserting the records in it for each iteration and then returning the full table:
CREATE OR REPLACE FUNCTION get_data(id bigint, lbound bigint, ubound bigint)
RETURNS TABLE(oid bigint, id bigint, val double precision) AS
$BODY$
#Creates the temp table
plpy.execute("""CREATE TEMP TABLE temp_results(oid bigint, id bigint, val double precision)
ON COMMIT DROP""")
plan = plpy.prepare("INSERT INTO temp_results SELECT oid, id, val FROM _get_data($1, $2);",
['bigint', 'bigint'])
#Inserts the results in the temp table
for i in range(lbound, ubound+1):
plpy.execute(plan, [id, i])
#Returns the whole table
recs = plpy.execute("SELECT * FROM temp_results")
return recs
$BODY$
LANGUAGE plpython3u;
I created one table
CREATE TABLE human (chromosome text, position bigint,
hg01583 frozen<set<text>>,
hg03006 frozen<set<text>>,
PRIMARY KEY (chromosome, position)
)
and i created function
CREATE FUNCTION process(sample list<frozen<set<text>>>)
CALLED ON NULL INPUT
RETURNS text
LANGUAGE java
AS
$$
return leftsample==null?null:leftsample.getClass().toString()+" "+leftsample.toString();
$$;
when i issie CQL query
SELECT chromosome,position,hg01583, hg03006, process([hg01583,hg03006]) from human;
i got this error
SyntaxException: line 1:80 no viable alternative at input ',' ([[hg01583],..
how can i pass hg01583 ,hg03006 as list to process function?
With each as own argument like: SELECT chromosome, position, hg01583, hg03006, process(hg01583, hg03006) from human;
CREATE FUNCTION process(hg01583 frozen<set<text>>, hg03006 frozen<set<text>>)
CALLED ON NULL INPUT
RETURNS text
LANGUAGE java AS
$$
return hg01583==null? null : ...
$$;
If you want them to be dynamic, instead of creating fixed columns for each one make it a wide row and use a UDA to aggregate them with an accumulator function. like:
CREATE TABLE human (chromosome text, position bigint,
sample text,
value frozen<set<text>>
PRIMARY KEY (chromosome, position, sample)
)
SELECT count(*) FROM device_stats
WHERE orgid = 'XYZ'
AND regionid = 'NY'
AND campusid = 'C1'
AND buildingid = 'C1'
AND floorid = '2'
AND year = 2017;
The above CQL query returns correct result - 32032, in CQL Shell
But when I run the same query using QueryBuilder Java API , I see the count as 0
BuiltStatement summaryQuery = QueryBuilder.select()
.countAll()
.from("device_stats")
.where(eq("orgid", "XYZ"))
.and(eq("regionid", "NY"))
.and(eq("campusid", "C1"))
.and(eq("buildingid", "C1"))
.and(eq("floorid", "2"))
.and(eq("year", "2017"));
try {
ResultSetFuture tagSummaryResults = session.executeAsync(tagSummaryQuery);
tagSummaryResults.getUninterruptibly().all().stream().forEach(result -> {
System.out.println(" totalCount > "+result.getLong(0));
});
I have only 20 partitions and 32032 rows per partition.
What could be the reason QueryBuilder not executing the query correctly ?
Schema :
CREATE TABLE device_stats (
orgid text,
regionid text,
campusid text,
buildingid text,
floorid text,
year int,
endofwindow timestamp,
categoryid timeuuid,
devicestats map<text,bigint>,
PRIMARY KEY ((orgid, regionid, campusid, buildingid, floorid,year),endofwindow,categoryid)
) WITH CLUSTERING ORDER BY (endofwindow DESC,categoryid ASC);
// Using the keys function to index the map keys
CREATE INDEX ON device_stats (keys(devicestats));
I am using cassandra 3.10 and com.datastax.cassandra:cassandra-driver-core:3.1.4
Moving my comment to an answer since that seems to solve the original problem:
Changing .and(eq("year", "2017")) to .and(eq("year", 2017)) solves the issue since year is an int and not a text.
I am having troubles with using now() function with timestamp type.
Please take a look at the following code:
Table creation:
CREATE TABLE "Test" (
video_id UUID,
upload_timestamp TIMESTAMP,
title VARCHAR,
views INT,
PRIMARY KEY (video_id, upload_timestamp)
) WITH CLUSTERING ORDER BY (upload_timestamp DESC);
The problematic INSERT query:
INSERT INTO "Test" (video_id, upload_timestamp, title, views)
VALUES (uuid(), now(), 'Test', 0);
The INSERT query seems looking fine to me. However, when I execute it, I see the following error:
Unable to execute CQL script on 'XXX': cannot assign result of function now (type timeuuid) to upload_timestamp (type timestamp)
What I am doing wrong here?
I use DataStax Enterprise 4.5.2
now() returns a timeuuid, not a timestamp. You clould try dateOf(now()). Have a read of this from the docs:
dateOf and unixTimestampOf
The dateOf and unixTimestampOf functions take a timeuuid argument and
extract the embedded timestamp. However, while the dateof function
return it with the timestamp type (that most client, including cqlsh,
interpret as a date), the unixTimestampOf function returns it as a
bigint raw value.
I have the following table in cassandra;
CREATE TABLE reports (
c_date text,
c_n int,
c_id timeuuid,
report_id bigint,
report text,
PRIMARY KEY ((c_date, c_n), c_id)
)
c_date is for querying reports by date.
c_n is the number of nodes to prevent hotspots(number of nodes to distribute data evenly).
c_id is the inserted timeuuid.
My select query (cql 3) is the following;
select report, dateOf(c_id), report_id
from keyspace.reports
where c_date = '2013-08-02' and
c_n = 1 and
c_id > minTimeuuid('2013-08-02 02:52:10-0400');
I have successfully get the result set;
However, when I use cql_get_rows() function implemented on another example (here),
the timestamp (dateOf(id)) cannot be parsed correctly and bigint fields yield the following warning;
PHP Warning: unpack(): Type N: not enough input, need 4, have 0
in /home/arascan/my-project/tools/vendor/phpcassa/lib/phpcassa/Schema/DataType/LongType.php on line 47
The returned data from cql_get_rows() is the following;
[0] => Array
(
[reportid] => 281474976712782
[report] => some_report
[dateOf(c_id)] => d:1375426331.32100009918212890625;
)
How can I prevent this function throw warning and get the timestamp in date format?
(Please don't suggest # usage)