Normally in C++ programming language, the plus means addition, in the example below
int x;
x += 1;
However in plsql query, I am confused about the same usage. That usage does not mean addition. In that case, what is the meaning of =+ ?
Select c.* From alf_numeric a, run_of_id b, tail_of_st c
WHERE category_id IN(33,36) AND a.flow_id =+ b.flow_id
Any idea?
This:
...
FROM alf_numeric a, run_of_id b
WHERE a.flow_id = b.flow_id (+)
would mean:
...
FROM alf_numeric a
LEFT JOIN run_of_id b
ON a.flow_id = b.flow_id
My guess is that:
a.flow_id =+b.flow_id
is parsed as the (simple):
a.flow_id = (+b.flow_id)
and so is the same as:
a.flow_id = b.flow_id
It looks to me that the '+' part of '=+' is a no-op. Try running the following statements:
CREATE TABLE test1 (v1 NUMBER);
INSERT INTO test1(v1) VALUES (-1);
INSERT INTO test1(v1) VALUES (1);
CREATE TABLE test2(v2 NUMBER);
INSERT INTO test2(v2) VALUES (-1);
INSERT INTO test2(v2) VALUES (1);
SELECT *
FROM test1 t1
INNER JOIN test2 t2
ON (t1.v1 = t2.v2)
WHERE t1.v1 =+ t2.v2;
which returns
V1 V2
-1 -1
1 1
Thus, it appears the '+' operator isn't doing anything, it's just answering whatever is there. As a test of this, run the following statement:
SELECT V1, +V1 AS PLUS_V1, ABS(V1) AS ABS_V1, -V1 AS NEG_V1 FROM TEST1;
and you'll find it returns
V1 PLUS_V1 ABS_V1 NEG_V1
-1 -1 1 1
1 1 1 -1
which seems to confirm that a unary '+' is effectively a no-op.
Share and enjoy.
In your SELECT statement, the clause
a.flow_id =+b.flow_id
is mainly a comparison. It tests whether the value of a.flow_id is equal to the value of b.flow_id. So the + operator in this case is an arithmetic operator working on a single operand. It turns the sign of the value to positive.
Update:
It seems I was slightly wrong. The operator doesn't change the sign. It has basically no effect.
It's probably a typo for the old left join syntax in Sybase, which would be =* instead of =+. If that's true, you can rewrite the query in a clearer way using joins, like:
select c.*
From alf_numeric a
left join
run_of_id b
on a.flow_id = b.flow_id
cross join
tail_of_st c
WHERE category_id IN(33,36)
Which would basically return the entire table tail_of_st for each entry in alf_numeric, with a filter on category_id (not sure what table that's in.) A mysterious query!
In your C++ example, the + designates the positive sign, it has nothing to do with addition. Just as you can write x = -1, you can also write x = +1 (which is equal to x = 1, since + as sign can be omitted - and is, in most cases, since it does in fact have no effect whatsoever). But both these cases are an assignment in C++, not an addition - no actual calculation is involved; you're probably thinking of x += 1 (the order is important!), which would increase x by 1.
In your SQL query, I think the + is supposed to have a special meaning - it should probably indicate an outer join. Although if I read that document correctly, it should actually be a.flow_id = b.flow_id (+); as it is here, I doubt that the query parser will recognize it as an outer join, but will instead just interpret it as a positive sign, just as in your C++ example.
I believe that's a join syntax thing. The standard way is to say something like tableA join tableB on <whatever> but some DBs, such as Sybase and Oracle support alternate syntax. In Sybase, it's =* or *=. Postgres probably does the same. From the format, I'd guess a right outer join, but it's hard to say. I looked in the PG docs, but didn't immediately see it.
BTW, in C you'd have x += 1 not x = +1.
Related
I have the following query :
SELECT A.*, B.* FROM Employee AS A
LEFT JOIN EmployeeHistory AS B ON +B.EmployeeId = CASE
WHEN DeptId=1 THEN SUBSTRING(FunctionRef,2,3)
WHEN DeptId=2 THEN SUBSTRING(FunctionRef,2,2) END
I want to understand the + before the +B.EmployeeId, since SQL Server isn't throwing an error
The SQL you have posted is not valid T-SQL. This is because after you define the alias for Employee as A you have an ON ("A" is for Employee? What A? A is for Apple, E is for Employee. Bad Habits to Kick : Using table aliases like (a, b, c) or (t1, t2, t3)). The first table in a FROM can't be followed by an ON, ON is for tables that you are joining to.
If the first ON is meant to be a JOIN, it does work: db<>fiddle. But all the + is doing is being a leading plus or concatenation operator (which depends on the data type of EmployeeID). SELECT +1, + ''; is perfectly valid (though odd) syntax. The + is basically doing nothing.
Disclaimer: The opening paragraph is based on the original SQL the OP posted, which they stated they had copy and pasted from a working environment.
The + is a unary plus sign. It is analogous to then unary minus (-) but it doesn't do anything. If the second argument is a string, then it is a unary string concatenator, once again doing nothing.
I'm not sure what the purpose is.
You can check this out to get an idea:
select ++++1, + '', +'abc'
Maybe you forgot to include the second line JOIN table2 as B. If you included that line the query could become valid.
The +B.EmployeeId expression can mean 0+B.EmployeeId and thus the plus sign would not have any effect.
I am building a SQL query inside a function. The functions parameters are my criterias for the WHERE clause. Parameters can be null too.
foo (1,2,3) => SELECT x FROM y WHERE a=1 AND b=2 AND c=3;
foo (null, 2, null) => SELECT x FROM y WHERE b=2;
My approach to do that in code is to add a very first alltime true in the WHERE-clause (e.g. 1=1 or NULL is NULL or 2 > 1)
So I do not need to handle the problem that the 1st WHERE condition is after a "WHERE" and all others are after a "AND".
String sql="SELECT x FROM y WHERE 1=1";
if (a!=null)
{
sql += " AND a="+a;
}
Is there a better term than 1=1 or my other samples to EXPLICITLY have a always true value? TRUE and FALSE is not working.
Oracle does not support a boolean type in SQL. It exists in PL/SQL, but can't be used in a query. The easiest thing to do is 1=1 for true and 0=1 for false. I'm not sure if the optimizer will optimize these out or not, but I suspect the performance impact is negligible. I've used this where the number of predicates is unknown until runtime.
I think this construct is superior to anything using nvl, coalesce, decode, or case, because those bypass normal indexes and I've had them lead to complicated and slow execution plans.
So, yes I'd do something like you have (not sure what language you're building this query in; this is not valid PL/SQL. Also you should use bind variables but that's another story):
sql = "SELECT x FROM y WHERE 1=1";
if (a != null)
{
sql += " AND a=" + a;
}
if (b != null)
{
sql += " AND b=" + b;
}
... etc.
I think this is better than Gordon Linoff's suggestion, because otherwise this would be more complicated because you'd have to have another clause for each predicate checking if there was a previous predicate, i.e. whether you needed to include the AND or not. It just makes the code more verbose to avoid a single, trivial clause in the query.
I've never really understood the approach of mandating a where clause even when there are no conditions. If you are constructing the logic, then combine the conditions. If the resulting string is empty, then leave out the where clause entirely.
Many application languages have the equivalent of concat_ws() -- string concatenation with a separator (join in Python, for instance). So leaving out the where clause does not even result in code that is much more complicated.
As for your question, Oracle doesn't have boolean values, so 1=1 is probably the most common approach.
use NVL so you can set a default value. Look up NVL or NVL2. Either might work for you.
check out: http://www.dba-oracle.com/t_nvl_vs_nvl2.htm
In sql the standard way to "default null" is to use coalesce. So lets say your input is #p1, #p2, and #p3
Then
select *
from table
where a = coalesce(#p1,a) and
b = coalesce(#p2,b) and
c = coalesce(#p3,c)
Thus if (as an example) #p1 is null then it will compare a = a (which is always true). If #p1 is not null then it will filter on a equals that value.
In this way null becomes a "wildcard" for all records.
you could also use decode to get the results you need since it is oracle
Select
decode(a, 1, x,null),
decode(b, 2, x,null),
decode(c, 3, x,null)
from y
What about using OR inside of the parentheses while ANDs exist at outside of them
SELECT x
FROM y
WHERE ( a=:prm1 OR :prm1 is null)
AND ( b=:prm2 OR :prm2 is null)
AND ( c=:prm3 OR :prm3 is null);
Can SQLite check set coverage using the IN operator?
ie
(SELECT n from nums where n < 4) IN (1,2,3,4)
(where nums is the set of whole numbers) would return true
I have searched the documents but can only find documents where they are only using a single value on the left of IN.
Tests have returned that it can, but I need to confirm this is a valid use case and not a side effect like the ability for SQLite to return aggregate queries without proper GROUP BY statements.
Documentation says no.
The IN and NOT IN operators take a single scalar operand on the left and a vector operand on the right formed by an explicit list of zero or more scalars or by a single subquery.
Emphasis mine
https://www.sqlite.org/lang_expr.html#in_op
The documentation says:
The IN and NOT IN operators take a single scalar operand on the left
So if you use a subquery on the left side, it is treated as a scalar subquery, which does not behave as you want it to:
The result of the expression is the value of the only column in the first row returned by the SELECT statement. If the SELECT yields more than one result row, all rows after the first are ignored.
To check for set coverage, you have to check if there is any element in the left set that is not in the right set:
WITH a(n) AS (
SELECT n
FROM nums
WHERE n < 4
),
b(n) AS (
VALUES (1), (2), (3), (4)
)
SELECT *
FROM a
WHERE NOT EXISTS (SELECT 1
FROM b
WHERE b.n = a.n);
Using Postgres 9.0, I need a way to test if a value exists in a given array. So far I came up with something like this:
select '{1,2,3}'::int[] #> (ARRAY[]::int[] || value_variable::int)
But I keep thinking there should be a simpler way to this, I just can't see it. This seems better:
select '{1,2,3}'::int[] #> ARRAY[value_variable::int]
I believe it will suffice. But if you have other ways to do it, please share!
Simpler with the ANY construct:
SELECT value_variable = ANY ('{1,2,3}'::int[])
The right operand of ANY (between parentheses) can either be a set (result of a subquery, for instance) or an array. There are several ways to use it:
SQLAlchemy: how to filter on PgArray column types?
IN vs ANY operator in PostgreSQL
Important difference: Array operators (<#, #>, && et al.) expect array types as operands and support GIN or GiST indices in the standard distribution of PostgreSQL, while the ANY construct expects an element type as left operand and can be supported with a plain B-tree index (with the indexed expression to the left of the operator, not the other way round like it seems to be in your example). Example:
Index for finding an element in a JSON array
None of this works for NULL elements. To test for NULL:
Check if NULL exists in Postgres array
Watch out for the trap I got into: When checking if certain value is not present in an array, you shouldn't do:
SELECT value_variable != ANY('{1,2,3}'::int[])
but use
SELECT value_variable != ALL('{1,2,3}'::int[])
instead.
but if you have other ways to do it please share.
You can compare two arrays. If any of the values in the left array overlap the values in the right array, then it returns true. It's kind of hackish, but it works.
SELECT '{1}' && '{1,2,3}'::int[]; -- true
SELECT '{1,4}' && '{1,2,3}'::int[]; -- true
SELECT '{4}' && '{1,2,3}'::int[]; -- false
In the first and second query, value 1 is in the right array
Notice that the second query is true, even though the value 4 is not contained in the right array
For the third query, no values in the left array (i.e., 4) are in the right array, so it returns false
unnest can be used as well.
It expands array to a set of rows and then simply checking a value exists or not is as simple as using IN or NOT IN.
e.g.
id => uuid
exception_list_ids => uuid[]
select * from table where id NOT IN (select unnest(exception_list_ids) from table2)
Hi that one works fine for me, maybe useful for someone
select * from your_table where array_column ::text ilike ANY (ARRAY['%text_to_search%'::text]);
"Any" works well. Just make sure that the any keyword is on the right side of the equal to sign i.e. is present after the equal to sign.
Below statement will throw error: ERROR: syntax error at or near "any"
select 1 where any('{hello}'::text[]) = 'hello';
Whereas below example works fine
select 1 where 'hello' = any('{hello}'::text[]);
When looking for the existence of a element in an array, proper casting is required to pass the SQL parser of postgres. Here is one example query using array contains operator in the join clause:
For simplicity I only list the relevant part:
table1 other_name text[]; -- is an array of text
The join part of SQL shown
from table1 t1 join table2 t2 on t1.other_name::text[] #> ARRAY[t2.panel::text]
The following also works
on t2.panel = ANY(t1.other_name)
I am just guessing that the extra casting is required because the parse does not have to fetch the table definition to figure the exact type of the column. Others please comment on this.
I've a table with a varchar column (A) and another integer column(B) indicating the type of data present in A. If B is 0, then A will always contain numeric digits.
So when I form an sql like this
SELECT COUNT(*) FROM TAB WHERE B = 0 AND TO_NUMBER(A) = 123;
I get an exception invalid number.
I expect B = 0 to be evaluated first, and then TO_NUMBER(A) second, but from the above scenario I suspect TO_NUMBER(A) is evaluated first. Is my guess correct?
In contrast to programming languages like C, C#, Java etc., SQL doesn't have so called conditional logical operators. For conditional logical operators, the right operand is only evaluated if it can influence the result. So the evaluation of && stops if the left operand returns false. For || it stops if the left operand returns true.
In SQL, both operands are always evaluated. And it's up to the query optimizer to choose which one is evaluated first.
I propose you create the following function, which is useful in many cases:
FUNCTION IS_NUMBER(P_NUMBER VARCHAR2)
RETURN NUMBER DETERMINISTIC
IS
X NUMBER;
BEGIN
X := TO_NUMBER(P_NUMBER);
RETURN X;
EXCEPTION
WHEN OTHERS THEN RETURN NULL;
END IS_NUMBER;
Then you can rewrite your query as:
SELECT COUNT(*) FROM TAB WHERE B = 0 AND IS_NUMBER(A) = 123;
You can also use the function to check whether a string is a number.
Here's a simple way to force the check on B to occur first.
SELECT COUNT(*) FROM TAB
WHERE 123 = DECODE(B, 0, TO_NUMBER(A), NULL);
you can use subquery to be confident in the correctness of the result
select /*+NO_MERGE(T)*/ count(*)
from (
select *
from TAB
where B = 0
) T
where TO_NUMBER(A) = 123
in your particular example, you can compare varchars like this:
SELECT COUNT(*) FROM TAB WHERE B = 0 AND A = '123';
or if you trust oracle to do the implicit conversions, this should almost always work (i don't know in what cases it won't work, but it would be hard to debug if something went wrong)
SELECT COUNT(*) FROM TAB WHERE B = 0 AND A = 123;
It should test B = 0 first.
I not sure your guess is correct or not though without seeing sample data.
SELECT *
FROM DUAL
WHERE 1=0 AND 1/0=0
You can try add 1/0 = 0 as the last statement (like this query)
to your query to know if Oracle short circuits the logical operator.
sqlfiddle here.