Setting a variable in ANSI SQL - sql

I am new to SQL and have been searching for a way to set variables in ANSI SQL. I have this:
select * from table1
where first_date > '2014-01-01'
and where second_date = '2014-01-01'
and where third_date < '2014-01-01'
but I am hoping for something like:
set x = '2010-12-31'
select * from table1
where first_date > x
and where second_date = x
and where third_date < x
I read about stored procedures but it seems like overkill for something so seemingly simple. I'm running on Netezza but I'd like a general solution that can also work on other databases.

Standard (ANSI) SQL does not have variables. But what you can do in standard SQL is use a common table expression to only have the value once.
The following is ANSI SQL:
with data (the_date) as (
values (date '2014-01-01')
)
select *
from table1
where first_date > (select the_date from data)
and second_date = (select the_date from data)
and third_date < (select the_date from data);
The above would work on most DBMS. Not all of them support the values clause like that, but that can usually be worked around using a plain select statement instead.
As I have never used Netezza I have no idea if it supports the row constructor (the values clause) or common table expressions (the with clause)
Also some SQL clients offer the ability to define variables that are replaced before the SQL is actually sent to the database server.

a_horse_with_no_name's solution is the only pure SQL solution I know that doesn't go into procedural SQL extenion territory. There is another solution that is not strictly what you asked for as it is specific to the NZSQL CLI only, but you can use variables there like this.
TESTDB.ADMIN(ADMIN)=> \set x '\'2014-01-01\''
TESTDB.ADMIN(ADMIN)=>
SELECT *
FROM table1
WHERE first_date < :x
AND second_date = :x
AND third_date = :x;

Related

hive subquery must have a from clause?how to avoid it?

I met a problem in hive sql:
this sql is ok:
select 20181102 as my_date
but this don't work:
select * from (select 20181107 as my_date) c
the error is:
Error in semantic analysis: ERROR-0-HIVE:00003:{semantic error => sub query must have a from clause!!}}
I really need a sql only with select some constants but no from table
how to avoid this error?
probably you should to find the equivalent of this date and try, for example in mysql is CURDATE
select * from (select CURDATE as my_date from dual) c
but if you want the actual date I think you'd better do something of similar of this
select * from (select DATE(20181107,'YYYYMMDD') as my_date from dual) c
you should to see the documentation of your database
for example you can use something of similar
TO_DATE('07-OCT-18','dd-MON-yy')
or
TO_DATE('07-OCT-18')

PostgreSQL limiting results by year

i have a working PostgreSQL query, column "code" is common in both tables and table test.a has date column and i want to limit search results on year, date format is like ( 2010-08-25 )
SELECT *
FROM test.a
WHERE form IN ('xyz')
AND code IN (
SELECT code
FROM test.city)
any help is appreciated
To return rows with date_col values in the year 2010:
SELECT *
FROM test.a
WHERE form = 'xyz'
AND EXISTS (
SELECT 1
FROM test.city
WHERE code = a.code
)
AND date_col >= '2010-01-01'
AND date_col < '2011-01-01';
This way, the query can use an index on date_col (or, ideally on (form, date_col) or (form, code, date_col) for this particular query). And the filter works correctly for data type date and timestamp alike (you did not disclose data types, the "date format" is irrelevant).
If performance is of any concern, do not use an expression like EXTRACT(YEAR FROM dateColumn) = 2010. While that seems clean and simple to the human eye it kills performance in a relational DB. The left-hand expression has to be evaluated for every row of the table before the filter can be tested. What's more, simple indexes cannot be used. (Only an expression index on (EXTRACT(YEAR FROM dateColumn)) would qualify.) Not important for small tables, crucial for big tables.
EXISTS can be faster than IN, except for simple cases where the query plan ends up being the same. The opposite NOT IN can be a trap if NULL values are involved, though:
Select rows which are not present in other table
If by "limit" you mean "filter", then I can give you an option
SELECT
*
FROM
test_a
WHERE
form IN ('xyz')
AND code IN (
SELECT code
FROM test_city
)
AND EXTRACT(YEAR FROM dateColumn) = 2010;
db-fiddle for you to run and play with it: https://www.db-fiddle.com/f/5ELU6xinJrXiQJ6u6VH5/6

OrientDB - Queries with timezone

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;
/

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;