OrientDB - Queries with timezone - sql

I need to query orientDB to retrieve data aggregated by day.
E.g.:
SELECT OCCURRENCE, COUNT(1) AS NBR_VALUES FROM
(
SELECT END_PROCESSING.asDate().format('yyyy-MM-dd').asDate().asLong() AS OCCURRENCE
FROM MY_TABLE
WHERE END_PROCESSING >= ? AND END_PROCESSING <= ?
)
GROUP BY OCCURRENCE
However I need to perform this aggregation based on my client timezone (web browser).
Ideally it would be something similar to this:
SELECT END_PROCESSING.asDate('Europe/London')
Is there a way to achieve this or will I need to do this aggregation on the above layer (Java)?

Suggesting per my experience with oracle db.
How about making this a stored procedure? You can return the object with data. Accept the limits as parameters. Get the parameters from upper layer(javascript/java).
I mean something like(Please translate to your db syntax):
FUNCTION get_data(I_time1 TIMESTAMP, I_time2 TIMESTAMP)
RETURNS --your object type here---
IS
BEGIN
SELECT OCCURRENCE, COUNT(1) AS NBR_VALUES INTO --your objects here--
FROM
(
SELECT END_PROCESSING.asDate().format('yyyy-MM-dd').asDate().asLong() AS OCCURRENCE
FROM MY_TABLE
WHERE END_PROCESSING >= I_time1 AND END_PROCESSING <= I_time2
)
GROUP BY OCCURRENCE;
RETURN --your object--
;
END;
/

Related

Looking for something like a Lag function but more complex (SQL)

Im racking my brain about how to do this and I dont think its possible but not sure what to even search for. So the below is a subset of the data (using example numbers)
and I want to use like a lag function to pull the value down then multiply by % column and have something like the below (using the new calculated value each time)
I have a feeling its not possible but fingers crossed. Using Redshift if it helps
Thanks in Advance
Amazon Redshift is based on Postgresql, and even if there are some differences (cmp. https://docs.aws.amazon.com/redshift/latest/dg/c_redshift-and-postgres-sql.html), it does include the lag() function (see https://docs.aws.amazon.com/redshift/latest/dg/r_WF_LAG.html).
So your statement should probably look something like this (works in postgres)
UPDATE yourtable
SET number = (q1.percentage * q1.prevnumber)
FROM (SELECT Months, percentage, lag(number) OVER (ORDER BY Months) as prevnumber
FROM yourtable) q1
WHERE yourtable.Months = q1.Months AND yourtable.Months > 0;
You can also include a condition to only update those fields that do not have a value yet by adding something like AND Number IS NULL to the last WHERE clause. And if you have multiple years, you need to take that into account in your ordering, of course.
Have a look at these two SO posts for more detailed discussions and examples:
Is there a way to access the "previous row" value in a SELECT statement?
PostgreSQL update query with "lag()" window function
EDIT: This query will not update all rows in a single pass, as the query is based on the original table entries and on updating the row of Month 10 will have a NULL value as one of the factors of the multiplication (number from Month 9).
There are different approaches you can use to reach your desired result. I have added two examples below. Both work in postgres and should also work in redshift:
(1) You can repeat the above UPDATE statement the appropriate number of times using a WHILE loop. The following function iteratively updates the table until no more rows exist where number is NULL:
CREATE OR REPLACE FUNCTION update_numbers() RETURNS void AS
$BODY$
BEGIN
WHILE (SELECT COUNT(*) FROM yourtable WHERE number IS NULL) > 0 LOOP
UPDATE yourtable
SET number = (q1.percentage * q1.prevnumber)
FROM (SELECT Months, percentage, lag(number) OVER (ORDER BY Months) as prevnumber
FROM yourtable) q1
WHERE yourtable.number IS NULL
AND yourtable.Months = q1.Months
AND yourtable.Months > 0;
END LOOP;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
(2) You can use a CURSOR to loop through the individual rows in which number is NULL and update each of them one at a time:
CREATE OR REPLACE FUNCTION update_numbers() RETURNS void AS
$BODY$
DECLARE
rec record;
prev numeric;
cur cursor for (SELECT * FROM yourtable WHERE number IS NULL ORDER BY Months) FOR UPDATE;
BEGIN
FOR rec in cur LOOP
SELECT prevnumber INTO prev FROM (SELECT Months, percentage, lag(number) OVER (ORDER BY Months) as prevnumber
FROM yourtable) q1 where q1.months = rec.months;
UPDATE yourtable
SET number = (percentage * prev)
WHERE CURRENT of cur;
END LOOP;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
Calling either of these two with
SELECT update_numbers();
updates all rows of your example table.

Use Ruby To Convert Any Query To Count Query

In my application I use PG to execute queries defined by the user in-app.
require 'pg'
database = PG.connect(*credentials)
query = 'select id, created_at from users where id % 2 = 0'
database.connection.exec(query)
Part of the application requires fetching a count before running the actual query so I use regex to convert the query to a count query. (Assume LIMIT and ORDER BY are not allowed)
query = 'select id, created_at from users where id % 2 = 0'
query.gsub!(%r{(?<=SELECT)[^\/]+(?=FROM)}, ' count(*) ')
count = database.exec(query).first['count'].to_i
But if the query includes CTE's and/or sub-queries...
query = 'with new_table as (select id from users where id % 2 = 0)
select created_at, name from users where id in (select * from new_table)'
the above regex doesn't work, and I haven't been able to figure out another regex based solution.
Using SQL, Ruby, or REGEX, how could I convert any query a read-only db user could perform into a count query WITHOUT wrapping the query in its own CTE or just running the query and counting the results?
More simply, given a query, how can one get the row count for that query without actually running the full query?
Any engineers at Looker, PeriscopeData, or Mode should have this one in the bag :-)
Modifying SQL queries with a regex is a non-starter for all the reasons you don't try to modify XML with a regex: you need something which understands the grammar. What you're looking for is a SQL Query Builder.
A SQL Query Builder is sort of like an ORM without the ORM. You use it to write SQL queries using method calls, not strings, but you don't have to tell it what all your tables and columns are like an ORM, nor do you have to make classes for all your tables. It just makes SQL queries.
Your query is held as an object and only turned into SQL when it's time to communicate with the database. If you want to modify the query, you do it with method calls and regenerate the SQL. So you can add where clauses and group bys and limits and add more rows to select and join tables and, yes, count.
They also will often smooth over SQL incompatibilities for you, so the same code can run on MySQL or SQLite or Postgresql or Oracle.
A good non-Ruby one is Knex.js in Javascript. I'm having a hard time finding a pure SQL Query Builder for Ruby. The ones I've found (ActiveRecord, Sequel, squeel, and ARel) are all ORMs and require you to set up classes and schemas and all that. The only one I could find for Ruby that isn't an ORM is qdsl.
Easy way: create a new query from your existing one by just surrounding it to convert it into a subquery:
require 'pg'
database = PG.connect(*credentials)
query = 'select id, created_at from users where id % 2 = 0'
# Create a `count` query, based on the existing one.
# The original query must NOT end with ';'
count_query = 'SELECT count(*) AS count FROM (' + query + ') AS q0'
database.connection.exec(count_query)
# Follow on
database.connection.exec(query)
This may not be the most efficient way of getting the count, but I think it is the simplest and (probably) the less error-prone. It assumes that the original query is well-formed, and that it does not call functions with side-effects [a practice that should be reserved for very few use-cases].
Assuming the users table is similar to:
CREATE TABLE users AS
SELECT * FROM
(VALUES
(1::integer, 'name1'::text, now()::timestamp),
(2, 'name2', now() - interval '1 hour'),
(3, 'name3', now() - interval '2 hours'),
(4, 'name4', now() - interval '2 hours')
) x(id, name, created_at) ;
This solution works with WITH clases, because the following SQL query is legal:
SELECT count(*) FROM
(
with new_table as (select id from users where id % 2 = 0)
select created_at, name from users where id in (select * from new_table)
) AS q0 ;
... and returns 2 as expected.

select row of minimum value without using rownum

I'm using Oracle SQL and i need some help with a query.
In the following query i'm selecting some rows with a simple condition (never mind hat kind of). From the output rows, i need to select the row with minimum value of DATE. For that, i'm using ROWNUM.
SELECT *
FROM(
SELECT NAME, DATE
FROM LIST
WHERE NAME = 'BLABLA'
ORDER by DATE)
WHERE ROWNUM = 1;
However, this query must fit to any other SQL languages, and therefore i need to write this query without ROWNUM.
Is there a simple way to write this query without using ROWNUM?
Unfortunately, row limit syntax differs between RDBMS.
The following is portable between SqlServer, Oracle and PostGres:
SELECT *
FROM (
SELECT NAME, DATE, ROW_NUMBER() OVER (ORDER by DATE) AS RowNum
FROM LIST
WHERE NAME = 'BLABLA'
) X
WHERE RowNum = 1;
However, other DB's syntax is different, e.g. MySql's LIMIT
select * from LIST
where Date=(select min(date) from LIST where Name='BLABLA' )
and Name='BLABLA'

How to create a temp variable in database oracle query?

Similar to programming languages, is it possible to create a temporary variable and define it a value? e.g.
String date = '12-MAY-12'
Select COUNT (*) FROM TABLEX WHERE TABLE_DATE < DATE;
What you are after can easily be achieved using Oracle PL/SQL. I assume you want this using SQL only. If that's the case, here is one way you could do that:
WITH
variable_table AS
(
SELECT
to_date('12-MAY-2012') v_date
FROM
dual
)
SELECT
COUNT (*)
FROM
TABLEX
WHERE
TABLE_DATE <
(
SELECT
v_date
FROM
variable_table
)
I hope this helps
The answer is, it depends.
It depends on environment you use.
For example, Allround Automations PL/SQL Developer accepts sign & before string for variables (values of them are asked during query execution):
SELECT COUNT (*)
FROM TABLEX
WHERE TABLE_DATE < &DATE;

HQL count from multiple tables

I would like to query my database using a HQL query to retrieve the total number of rows having a MY_DATE greater than SOME_DATE.
So far, I have come up with a native Oracle query to get that result, but I am stuck when writing in HQL:
SELECT
(
SELECT COUNT(MY_DATE)
FROM Table1
WHERE MY_DATE >= TO_DATE('2011-09-07','yyyy-MM-dd')
)
+
(
SELECT COUNT(MY_DATE)
FROM Table2
WHERE MY_DATE >= TO_DATE('2011-09-07','yyyy-MM-dd')
)
AS total
I actually have more than 2 tables but I keep having an IllegalArgumentException (unexpected end of subtree).
The working native Oracle basically ends with FROM dual.
What HQL query should I use to get the total number of rows I want?
First of, if you have a working SQL query, why not just use that instead of trying to translate it to HQL? Since you're returning a single scalar in the first place, it's not like you need anything HQL provides (e.g. dependent entities, etc...)
Secondly, do you have 'dual' mapped in Hibernate? :-) If not, how exactly are you planning on translating that?
That said, "unexpected end of subtree" error is usually caused by idiosyncrasies of Hibernate's AST parser. A commonly used workaround is to prefix the expression with '0 +':
select 0 + (
... nested select #1 ...
) + (
... nested select #2 ...
) as total
from <from what exactly?>