What is the difference between NOT and != operators in SQL? I can't understand the difference. I guess they are same.
NOT negates the following condition so it can be used with various operators. != is the non-standard alternative for the <> operator which means "not equal".
e.g.
NOT (a LIKE 'foo%')
NOT ( (a,b) OVERLAPS (x,y) )
NOT (a BETWEEN x AND y)
NOT (a IS NULL)
Except for the overlaps operator above could also be written as:
a NOT LIKE 'foo%'
a NOT BETWEEN x AND y
a IS NOT NULL
In some situations it might be easier to understand to negate a complete expression rather then rewriting it to mean the opposite.
NOT can however be used with <> - but that wouldn't make much sense though: NOT (a <> b) is the same as a = b. Similarly you could use NOT to negate the equality operator NOT (a = b) is the same as a <> b
This question actually makes a lot more sense than people give it credit for.
Firstly, original SQL not-equal operator was <>, and only later on the C-style != was added as far as I know. I personally always use <> as != looks strange to me, but I'm old school.
Secondly, of course the original asker didn't mean to compare NOT with !=, but rather the difference between NOT a = b vs. a != b. And intuitively there should be a difference, but for all I know there isn't.
To make this all clear, here is an example session run on PostgreSQL (in Oracle you need more weird stuff such as SELECT ... FROM DUAL UNION ..., etc., which I avoid for the sake of brevity):
db=# with tst(a, b) as ( values (1,2), (2,3), (4, null) ) select * from tst;
a | b
---+---
1 | 2
2 | 3
4 |
(3 rows)
db=# with tst(a, b) as ( values (1,2), (2,3), (4, null) ) select * from tst where b = 2;
a | b
---+---
1 | 2
(1 row)
db=# with tst(a, b) as ( values (1,2), (2,3), (4, null) ) select * from tst where b != 2;
a | b
---+---
2 | 3
(1 row)
db=# with tst(a, b) as ( values (1,2), (2,3), (4, null) ) select * from tst where not b = 2;
a | b
---+---
2 | 3
(1 row)
Here we may think that this last query should also have returned the row (4, NULL). But it didn't. In PostgreSQL I can actually inspect this further, as follows:
db=# with tst(a, b) as ( values (1,2), (2,3), (4, null) ) select *, b = 2 as beq2 from tst;
a | b | beq2
---+---+------
1 | 2 | t
2 | 3 | f
4 | |
(3 rows)
You see that the Boolean expression b = 2 is NULL for the case where b is NULL. However, when a Boolean expression is NULL it is treated as false, or rather not true. And when you negate it with NOT, the Boolean value of the expression stays NULL and therefore is still not true.
Unfortunately I know of no other way than to handle NULL cases explicitly, so I have to write:
db=# with tst(a, b) as ( values (1,2), (2,3), (4, null) ) select * from tst where b is null or b = 2;
a | b
---+---
1 | 2
4 |
(2 rows)
So, instead of writing NOT <Boolean expression> you always have to write a IS NULL OR b IS NULL OR ... OR z IS NULL OR f(a, b, ..., z) where a, b, ..., z are variables in the given Boolean expression f(...).
It would be so much easier if instead of just NOT there were the Boolean operators MAYBE and CANNOT. So you could write WHERE MAYBE b = 2 or WHERE CANNOT b = 2 instead of this complicated OR combination of a bunch of IS NULL tests before your actual condition.
!= is a binary operator that returns true if its two arguments are not equal to each other.
NOT is a unary operator, which reverses its argument, a Boolean expression.
For example, this expression: a < 10 is true when a is any value less than 10. This condition can be negated: NOT a < 10. Negating this condition makes it true in the opposite cases, i.e. when a not less than 10. It's the same as a >= 10.
The expression a != 10 is true when a is any value less than 10 or any value greater than 10. This is a completely different case from a condition negated with NOT.
Both NOT operator and != almost serve a similar purpose.Both are used in Where clause of an sql query.
NOT operator shows records when a particular condition is not true.
Example:
SELECT * FROM Employees
WHERE NOT Country='Germany'
will get you records with all employees with countries other than Germany.
The != operator similarly checks if the values of two operands are equal or not, if values are not equal then condition becomes true.
Example:
SELECT * FROM Employees
WHERE Country!='Germany'
will get you all rows with country column having country other than Germany.
Related
In SQL there are aggregation operators, like AVG, SUM, COUNT. Why doesn't it have an operator for multiplication? "MUL" or something.
I was wondering, does it exist for Oracle, MSSQL, MySQL ? If not is there a workaround that would give this behaviour?
By MUL do you mean progressive multiplication of values?
Even with 100 rows of some small size (say 10s), your MUL(column) is going to overflow any data type! With such a high probability of mis/ab-use, and very limited scope for use, it does not need to be a SQL Standard. As others have shown there are mathematical ways of working it out, just as there are many many ways to do tricky calculations in SQL just using standard (and common-use) methods.
Sample data:
Column
1
2
4
8
COUNT : 4 items (1 for each non-null)
SUM : 1 + 2 + 4 + 8 = 15
AVG : 3.75 (SUM/COUNT)
MUL : 1 x 2 x 4 x 8 ? ( =64 )
For completeness, the Oracle, MSSQL, MySQL core implementations *
Oracle : EXP(SUM(LN(column))) or POWER(N,SUM(LOG(column, N)))
MSSQL : EXP(SUM(LOG(column))) or POWER(N,SUM(LOG(column)/LOG(N)))
MySQL : EXP(SUM(LOG(column))) or POW(N,SUM(LOG(N,column)))
Care when using EXP/LOG in SQL Server, watch the return type http://msdn.microsoft.com/en-us/library/ms187592.aspx
The POWER form allows for larger numbers (using bases larger than Euler's number), and in cases where the result grows too large to turn it back using POWER, you can return just the logarithmic value and calculate the actual number outside of the SQL query
* LOG(0) and LOG(-ve) are undefined. The below shows only how to handle this in SQL Server. Equivalents can be found for the other SQL flavours, using the same concept
create table MUL(data int)
insert MUL select 1 yourColumn union all
select 2 union all
select 4 union all
select 8 union all
select -2 union all
select 0
select CASE WHEN MIN(abs(data)) = 0 then 0 ELSE
EXP(SUM(Log(abs(nullif(data,0))))) -- the base mathematics
* round(0.5-count(nullif(sign(sign(data)+0.5),1))%2,0) -- pairs up negatives
END
from MUL
Ingredients:
taking the abs() of data, if the min is 0, multiplying by whatever else is futile, the result is 0
When data is 0, NULLIF converts it to null. The abs(), log() both return null, causing it to be precluded from sum()
If data is not 0, abs allows us to multiple a negative number using the LOG method - we will keep track of the negativity elsewhere
Working out the final sign
sign(data) returns 1 for >0, 0 for 0 and -1 for <0.
We add another 0.5 and take the sign() again, so we have now classified 0 and 1 both as 1, and only -1 as -1.
again use NULLIF to remove from COUNT() the 1's, since we only need to count up the negatives.
% 2 against the count() of negative numbers returns either
--> 1 if there is an odd number of negative numbers
--> 0 if there is an even number of negative numbers
more mathematical tricks: we take 1 or 0 off 0.5, so that the above becomes
--> (0.5-1=-0.5=>round to -1) if there is an odd number of negative numbers
--> (0.5-0= 0.5=>round to 1) if there is an even number of negative numbers
we multiple this final 1/-1 against the SUM-PRODUCT value for the real result
No, but you can use Mathematics :)
if yourColumn is always bigger than zero:
select EXP(SUM(LOG(yourColumn))) As ColumnProduct from yourTable
I see an Oracle answer is still missing, so here it is:
SQL> with yourTable as
2 ( select 1 yourColumn from dual union all
3 select 2 from dual union all
4 select 4 from dual union all
5 select 8 from dual
6 )
7 select EXP(SUM(LN(yourColumn))) As ColumnProduct from yourTable
8 /
COLUMNPRODUCT
-------------
64
1 row selected.
Regards,
Rob.
With PostgreSQL, you can create your own aggregate functions, see http://www.postgresql.org/docs/8.2/interactive/sql-createaggregate.html
To create an aggregate function on MySQL, you'll need to build an .so (linux) or .dll (windows) file. An example is shown here: http://www.codeproject.com/KB/database/mygroupconcat.aspx
I'm not sure about mssql and oracle, but i bet they have options to create custom aggregates as well.
You'll break any datatype fairly quickly as numbers mount up.
Using LOG/EXP is tricky because of numbers <= 0 that will fail when using LOG. I wrote a solution in this question that deals with this
Using CTE in MS SQL:
CREATE TABLE Foo(Id int, Val int)
INSERT INTO Foo VALUES(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)
;WITH cte AS
(
SELECT Id, Val AS Multiply, row_number() over (order by Id) as rn
FROM Foo
WHERE Id=1
UNION ALL
SELECT ff.Id, cte.multiply*ff.Val as multiply, ff.rn FROM
(SELECT f.Id, f.Val, (row_number() over (order by f.Id)) as rn
FROM Foo f) ff
INNER JOIN cte
ON ff.rn -1= cte.rn
)
SELECT * FROM cte
Not sure about Oracle or sql-server, but in MySQL you can just use * like you normally would.
mysql> select count(id), count(id)*10 from tablename;
+-----------+--------------+
| count(id) | count(id)*10 |
+-----------+--------------+
| 961 | 9610 |
+-----------+--------------+
1 row in set (0.00 sec)
Is there a common pattern how to store a condition like this in database (postgresql) to then in the easy way fetch these data from DB and in Frontend compare this with our value SE on the Frontend (to get the proper "value"):
condition value
SE < 2 foo
2 ≤ SE <3 bar
3 ≤ SE <4 foo2
4 ≤ SE bar2
Thanks
This sounds like a good case for a range column
create table data
(
valid_between int4range,
value text
);
insert into data (valid_between, value)
values
('(,2)', 'foo'), -- from infinity to 2
('[2,3)', 'bar'),
('[3,4)', 'foo2'),
('[4,)', 'bar2'); -- from 4 to infinity
To find the rows that are valid for the value 3 use the #> operator
select *
from data
where valid_between #> 3
A range column can efficiently be indexed to allow for fast searches.
The easiest way is probably to make two columns "lower bound" and "upper bound" like this:
LB UB ...
-INF 2
2 3
3 5
4 INF
Then to query a item by condition, use something like:
SELECT value FROM (table) WHERE LB <= SE AND SE < UB;
Store the lower bound only and then use lead to figure it out on the fly:
Threshold Value
0 foo
2 bar
3 foob
4 barf
with CTE as
(
select t1.*, lead(threshold) over(order by threshold) as nextone
from my_table
)
select CTE.value
from CTE
where my_value >= threshold
and (my_value < nextone or nextone is null)
I have the following example table.
1 2 3
A| |B -- Row 1
| |A -- Row 2
|B| -- Row 3
| | -- Row 4
A|A|A -- Row 5
C| |C -- Row 6
My aim is to systematically filter 'out' rows (presumably using != WHERE clauses). I know how to filter 'in' rows using = WHERE clauses but am unsure if it is possible to filter 'out' rows. Please see the following three examples:
1) Filter out A (i.e. leave any rows containing B,C or blank):
--> This should return everything apart from row 5 because every other row contains at least 1 B, C or blank cell
2) Filter out A AND Blanks (i.e. leave any rows containing B or C):
--> This should return rows 1, 3, 6 because each of these rows contains a B or a C
3) Filter out blanks (i.e. leave any rows containing A,B or C):
--> Return rows 1, 2, 3, 5, 6 leaving out Row 4 because this does not include a A, B or a C
A function to generate a query using an = clause would be:
void filterInRows(String colFilter)
{
List uniqueCols = ['A', 'B', 'C', ''];
String query = 'SELECT * FROM Test WHERE ';
int filterCounter = 0;
uniqueCols.forEach((String col)
{
if(col != colFilter)
{
query += (filterCounter != 0) ? ' AND ' : '';
query += "One = '$col' OR Two = '$col' OR Three = '$col'";
filterCounter++;
}
});
query += ';';
}
For example, if we call filterInRows('A') then we get back:
SELECT * FROM Test WHERE One = 'B' OR Two = 'B' OR Three = 'B' AND One = 'C' OR Two = 'C' OR Three = 'C' AND One = '' OR Two = '' OR Three = '';
Which solves the first example above. However, I am stuck in writing a function/query that would allow me to achieve the same thing but filtering rows out rather than in. Queries such as the following fail to achieve this for obvious reasons:
SELECT * FROM Test WHERE One != 'A' OR Two != 'A' OR Three != 'A';
SELECT * FROM Test WHERE One != 'A' AND Two != 'A' AND Three != 'A';
I am using SQLite. The code above is written in Dart but is just an example - happy for counter examples in any other language. My aim is to filter stuff out rather than filter stuff in. I believe you need to do this using != but I am open to another method using different keywords if they exist. Please let me know if I have not explained this problem clearly. Thanks in advance.
Use is not:
SELECT *
FROM Test
WHERE One IS NOT 'A' AND Two IS NOT 'A' AND Three IS NOT 'A';
As the documentation explains, this is the NULL-safe operator in SQLite:
The IS and IS NOT operators work like = and != except when one or both
of the operands are NULL. In this case, if both operands are NULL,
then the IS operator evaluates to 1 (true) and the IS NOT operator
evaluates to 0 (false). If one operand is NULL and the other is not,
then the IS operator evaluates to 0 (false) and the IS NOT operator is
1 (true).
In ANSI SQL, IS is IS NOT DISTINCT FROM. Some databases use <=>.
If I have NOT ( 1 <> 1 AND NULL <> 1 )
I can see SQL turning this into in the execution plan XML: ( 1 = 1 OR NULL = 1)
If you would literally evaluate the former expression, the True AND Null would be Null and would eliminate the row. However, the compiled expression can return a row due to the OR.
Can I assume that this type of compilation is guaranteed to always happen? SQL Server would never attempt to bring the convoluted logic forward into the compiled plan? Is there some documentation on this?
This article was pretty helpful, but I am just missing a piece of the puzzle:
https://www.simple-talk.com/sql/learn-sql-server/sql-and-the-snare-of-three-valued-logic/
Here is a SQL example
SELECT 1
FROM T T
LEFT JOIN T2 T2 --t2 has zero rows
ON T.id = t2.t_id
WHERE NOT ( T.id <> 99 AND T2.id <> 99 )
From my experience with SQL, I know that under normal circumstances (without short circuit evaluation) T2.id <> 99 effectively turns the left join into an inner join. That was the behavior I was initially expecting. I was surprised when this filter actually worked.
TL;DR The "compiled result" is not a helpful concept. What matters is the "specified result"--specified by the language definition. A DBMS must make the statement act the way you wrote it.
The truth [sic] table for AND in your link is wrong. AND with False is always False and OR with True is always True in SQL.
Comparisons in SQL return True, False or Unknown. Unknown can arise from a comparison to NULL or a 3VL logic connective (AND/OR/NOT etc) on Unknown. "NULL" is not a literal. True, False & Unknown are values with (assorted) literals in the SQL standard, but not in most DBMSs. (And Unknown can be returned as NULL.) IS is not a comparison; IS NULL and IS NOT NULL are unary 3Vl logic connectives and so are the similar ones named with TRUE, FALSE & UNKNOWN. They always return True or False.
True AND Null would be Null and would eliminate the row. However, the
compiled expression can return a row due to the OR.
No. The truth [sic] table for AND in your link is wrong. AND with False is always False and OR with True is always True in SQL. So your AND is always False from the NOT of False from the AND of False from 1 <> 1 and your OR is always True from 1 = 1. No matter what the other comparisons return (True, False or Unknown). If you work through these two expressions using the (correct) SQL truth tables), they both always give the same result, True.
One has to be very careful about rewriting conditions in SQL. One can interchange NOT (E1 *comparison* E2) by E1 *NOT-comparison* E2 or NOT (E IS ?) and E IS NOT ?. One can safely rewrite an expression using standard logic identities/rules if no value ever IS NULL. One can also safely apply rewrite rules to
(E1 *comparison* E2)
AND E1 IS NOT NULL AND E2 IS NOT NULL
Also beware that you must properly use an Unknown final result, which includes not matching for a WHERE but not failing for a constraint.
SELECT 1
FROM T T
LEFT JOIN T2 T2 --t2 has zero rows
ON T.id = t2.t_id
WHERE NOT ( T.id <> 99 AND T2.id <> 99 )
LEFT JOIN returns the rows of INNER JOIN plus unmatched rows of T extended by T2 columns NULL. (With T2 empty, the INNER JOIN is empty and all rows of T are unmatched.) All the extended rows have T2.id <> 99 Unknown since T2.id is NULL. For T.id = 99 the AND is False and the NOT is True; the WHERE returns all rows. For T1.id any other integer or NULL, the AND will be Unknown, the NOT will be Unknown; the WHERE returns no rows.
(There is no "short ciruit" evaluation of conditions in SQL. Every argument of a connective must be defined.)
If you would literally evaluate the former expression, the True AND Null would be Null and would eliminate the row.
No. You are evaluating the expression. NOT ( 1 <> 1 AND NULL <> 1 ) is NOT (FALSE AND UNKNOWN) is NOT FALSE is TRUE.
( 1 = 1 OR NULL = 1) is TRUE OR UNKNOWN is TRUE. They are both equivalent.
NOT ( 1 <> 1 AND NULL <> 1 ) can be rewritten as NOT ((NOT (1=1)) AND (NOT (NULL = 1))). In regular two value logic, by De Morgan's Laws that can be rewritten as NOT (NOT ((1 = 1) OR (NULL = 1))) and then (1=1) OR (NULL = 1). As it turns out De Morgan's Laws also hold in the three value logic of SQL. This can be demonstrated by creating exhaustive truth tables for the two laws.
The truth table showing that one of De Morgan's Laws, (NOT A) OR (NOT B) is equivalent to NOT (A AND B), holds in SQL's three value logic:
A B | (NOT A) OR (NOT B) | equiv? | NOT (A AND B)
========================================================
T T | F T F F T | T | F T T T
T F | F T T T F | T | T T F F
T U | F T U U U | T | U T U U
-------------------------------------------------------
F T | T F T F T | T | T F F T
F F | T F T T F | T | T F F F
F U | T F T U U | T | T F F U
-------------------------------------------------------
U T | U U U F T | T | U U U T
U F | U U T T F | T | T U F F
U U | U U U U U | T | U U U U
The other law, (NOT A) AND (NOT B) is equivalent to NOT (A OR B) can similarly be demonstrated.
Can I assume that this type of compilation is guaranteed to always happen?
No, specific compilations are never (hardly ever) guaranteed. Barring bugs in SQL Server, the query plans chosen, the transformations applied, will return the results specified by a query.
Edited to add: Let T.id be 99 and T2.id be NULL. Then:
WHERE NOT ( T.id <> 99 AND T2.id <> 99 )
WHERE NOT (99 <> 99 AND NULL <> 99)
WHERE NOT (FALSE AND UNKNOWN)
WHERE NOT (FALSE)
WHERE TRUE
I have a table called NUMS with a single column n.
And I fill values 1,2,3,4,5,null in it.
Now a query
SELECT n FROM Nums
WHERE n IN (1, 2, null)
In this case I guess it's converted to
SELECT n FROM Nums
Where n = 1 OR n = 2 OR n = null
I am also comparing n with a null value which should yield unknown and it should return an empty set.But it's returning 1,2 (null is not returning, although included in IN operator)
Now a query
SELECT n FROM Nums WHERE n NOT IN(1, 2, null)
...gets converted to:
SELECT n FROM Nums
Where n!=1 AND n!=2 AND n!=null
Here what I said above works and it does not return anything.
Can anyone explain in detail what's happening.
This is because null = null is always false the operator to use for null is IS or IS NOT
You can use the query below for the expected output
SELECT n FROM Nums WHERE n IN (1,2) OR n IS NULL
[Edit]Thanx #Buckwad
OK I have found the answer
SELECT n FROM Nums
WHERE n NOT IN (1, 2, null)
evaluates to
SELECT n FROM Nums
n!=1 AND n!=2 AND n!=null
The outcome of last comparison will always be UNKNOWN.
and the truth table of AND shows that as soon as one Unknown is invloved in it (U,T)(U,F),(U,U) the reult can only be U or F (U=Unknown, F=False) and hence it will not be included in the result set.
In case of
SELECT n FROM Nums
WHERE n IN (1, 2, null)
equates to
SELECT n FROM Nums
WHERE n = 1 OR n =2 OR n=null
Now for the row with n=1, the operation n=1 will come as true
and for the row with n=2, the operation n=2 will come as true
and for all rows n=null will be unknown
So it gives 1 and 2 in the result set.
Hope u people liked it.
CAN ANYONE PLEASE MARK MY REPLY AS ANSWER
null is not returning, although included in IN operator
Because of the n = NULL evaluation; NULL can't equal NULL. It would need to be handled as n IS NULL (or similar appropriate syntax) to return the NULL row/record.
You cannot compare directly with null. To find whether the value of a column is null, you must use something along the lines of this:
SELECT n
FROM Nums
WHERE n IS NULL
I am also comparing n with a null value which should yield unknown and it should return an empty set.
it shouldn't
if you need in additional row filled with NULL values the best way imo is:
SELECT n FROM Nums WHERE n IN(1,2)
UNION
SELECT NULL
Now a query
SELECT n FROM Nums WHERE n NOT IN(1, 2, null)
...gets converted to:
Here what I said above works and it does not return anything.
thats right, because nothing can be equal to NULL and for NULL comparison IS NULL statement is used
If an IN list contains a NULL value anywhere, the result of the entire list is UNKNOWN
With the correct default of ANSI NULLS, when you compare NULL with NULL the result is not true, but UNKNOWN
SELECT n FROM Nums
WHERE n IN (1, 2)
Or n Is null
This will retrieve what you intend to get. As said by Mitch normally a comparison to Null yields UNKNOWN. This is because NULL itself is defined as an undefined value. It's like saying I lived in Nottingham, Birmingham and somewhere. Finding somewhere on the world map can prove a bit tricky as it is undefined.