SELECT * FROM table WHERE (a!=1 AND b!=2)
How can I select all rows where a is not 1 and b is not 2 in the same time?
That is - in PHP it'd be ($a!=1 && $b!=2), bringing rows for example like
a=1, b=6,
a=5, b=2,
...
(but not a=1, b=2)
What I am getting with MySQL equals to PHP's $a!=1 && $b!=2 (the same just without brackets), bringing rows like
a=7, b=9,
a=4, b=0,
...
(but never a=1, and never b=2)
Based on your example, you want or, not and:
SELECT t.*
FROM table t
WHERE a <> 1 OR b <> 2;
Although MySQL (and other databases) support != for inequality, the standard is =. If you want to allow NULL values, you might want:
SELECT t.*
FROM table t
WHERE a <=> 1 OR b <=> 2;
<=> is a NULL-safe inequality operator specific to MySQL.
Related
I have been little bit confused while reading MySQL documentation MySQL documentation
A row subquery is a subquery variant that returns a single row and can thus return more than one column value. Legal operators for row subquery comparisons are:
= > < >= <= <> != <=>
For "=" documentation provides good explanation:
SELECT * FROM t1 WHERE (column1,column2) = (1,1);
is same as:
SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;
But how do the ">" or "<" can compare two rows? What is "plain" variant for this operator?
create table example(a integer,b integer);
insert into example values (1,1);
insert into example values (1,2);
insert into example values (2,1);
select * from example where (a,b) > (1,1)
a | b
-----
1 | 2
2 | 1
Playground: http://www.sqlfiddle.com/#!9/88641/2
p.s.:
PostgreSQL have same behaviour.
Oracle fail with error "ORA-01796: this operator cannot be used with lists "
MySQL and PostgreSQL has same behaviour, let's read postgres documentation
The = and <> cases work slightly differently from the others. Two rows are considered equal if all their corresponding members are non-null and equal; the rows are unequal if any corresponding members are non-null and unequal; otherwise the result of the row comparison is unknown (null).
For the <, <=, > and >= cases, the row elements are compared left-to-right, stopping as soon as an unequal or null pair of elements is found. If either of this pair of elements is null, the result of the row comparison is unknown (null); otherwise comparison of this pair of elements determines the result. For example, ROW(1,2,NULL) < ROW(1,3,0) yields true, not null, because the third pair of elements are not considered.
So (a,b) = (c,d) evaluated as
a = c and b = d
But (a,b,) < (c,d) evaluated as
a < b or (a=c and b < c)
It's look very strange. And I have no guess how will be evaluated comparation of rows with 3 of more attributes;
There are three records like:
a=7 , b=836
a=8 , b=836
a=7 , b=839
I want to get the result without (a=7 and b=836).
the result is empty when execute the sql like select * from test where a!=7 and b!=836,
but it got the correct result by using select * from test where a<>7 or b<>836.
I have two questions:
Why 'a!=7 and b!=836' not equal !(a=7 and b=836)?
What's the different between the two conditions ?
'a!=7 and b!=836' and 'a<>7 or b<>836'
The difference is in your logic operators, and and or, in combination with parentheses.
select * from test where a!=7 and b!=836
This query would select where BOTH of your statements return true, that is both a is not 7, and b is not 836. This would return nothing, there is no record where both of these are true.
select * from test where !(a=7 and b=836)
When you put the parentheses around your and, you move the logic around. That statement means that all records NOT matching any record where both a is 7 and b is 836. So inside the parenthesis it matches the first record, then it inverts that selection.
select * from test where a<>7 or b<>836
The <> is the same as != (Link to documentation). But in this query you use or. So it will match any record where a is not 7, AND any record that is not 836. So would match both second and third row.
For more reading material, take a look at the De Morgan's Laws. !(a and b) equals !a or !b. More explanation here and here.
Actually != and <> exactly the same. See the documentation.
<> is sql standard, != non-standard.
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#operator_not-equal
Hello here is my SQL query :
WHERE table1.Regnumber IN (
CASE
WHEN #fRegNumber IS NOT NULL AND #fRegNumber<>-1 THEN #fRegNumber
ELSE (SELECT Regnumber FROM table2)
END
)
An error:
'Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.'
How can I fix this?
The problem is with this subquery.
(SELECT Regnumber FROM table2)
It's returning every regnumber from the table. In the context of the overall query, you have to pick just one. The first step in solving your problem is to decide which one you want and why.
Change to:
WHERE IF(#fRegNumber IS NOT NULL AND #fRegNumber<>-1,
table1.Regnumber = #fRegnumber),
table1.Regnumber IN (SELECT Regnumber FROM table2))
WHERE x IN can be used in two ways:
WHERE x IN (expr1, expr2, expr3, ...)
In this case, if you use a subquery as the expression, it must return just a single value. A subquery that returns multiple values will not be spliced in.
or:
WHERE x IN (subquery)
This is the format that allows a subquery to return multiple rows, and x will be tested against all of them.
Since you want to conditionalize whether to test against a single value or the results of a subquery, you must do that outside the IN clause, using IF.
There may be other ways to write this query as a LEFT JOIN.
I can see 2 approaches here. One keeping the CASE statement this way:
WHERE
CASE WHEN COALESCE(#fRegNumber, -1) == -1
THEN t1.regnumber IN (SELECT t2.regnumber FROM table2))
ELSE t1.regnumber = #fRegNumber
END
And the other one rephrasing the whole CASE statement into the appropriate logical operators:
WHERE
(COALESCE(#fRegNumber, -1) != -1 AND t1.regnumber = #fRegNumber) OR
(COALESCE(#fRegNumber, -1) == -1 AND t1.regnumber IN (SELECT t2.regnumber FROM table2))
I was wondering if there is way to store where clause conditions and not calculate them more than once in order to determine which one was satisfied.
Here is what I am talking about:
select col, col1>5 cond1, col2<400 cond2 from table where col1>5 or col2<400
I don't think you should worry about calculating the simple comparisons like col1 > 5 more than once for each row, but in order to save typing in a more complex query, you may do like this:
SELECT col, col1 > 5 AS cond1, col2 < 400 AS cond2
FROM table
HAVING cond1 or cond2
Using having instead of where gives access to the aliases introduced in the select clause.
Basically I store data in MySql 5.5. I use qt to connect to mysql. I want to compare two columns, if col1 is greater than col2, the count continues, but when col1 is less than col2, count finishes and exits. So this is to count how many rows under some condition at the beginning of column. Is it possible in mysql?
An example:
Col1 Col2
2 1
2 3
2 1
The count I need should return 1, because the first row meets the condition of Col1 > Col2, but the second row doesn't. Whenever the condition is not meet, counting exits no matter if following rows meet the condition or not.
SELECT COUNT(*)
FROM table
WHERE col1 > col2
It's a little difficult to understand what you're after, but COUNT(*) will return the number of rows matched by your condition, if that's your desire. If it's not, can you maybe be more specific or show example(s) of what you're going for? I will do my best to correct my answer depending on additional details.
You should not be using SQL for this; any answer you get will be chock full of comprimise and if (for example) the result set from your intial query comes back in a different order (due to an index being created or changed), then they will fail.
SQL is designed for "set based" logic - and you really are after procedural logic. If you have to do this, then
1) Use a cursor
2) Use an order by statement
3) Cross fingers
This is a bit ugly, but will do the job. It'll need adjusting depending on any ORDER etc you would like to apply to someTable but the principle is sound.
SELECT COUNT(*)
FROM (
SELECT
#multiplier:=#multiplier*IF(t.`col1`<t.`col2`,0,1) AS counter
FROM `someTable` t, (SELECT #multiplier := 1) v
HAVING counter = 1
) scanQuery
The #multiplier variable will keep multiplying itself by 1. When it encounters a row where col1 < col2 it multiplies by 0. It will then continue multiplying 0 x 1. The outer query then just sums them up.
It's not ideal, but would suffice. This could be expanded to allow you to get those rows before the break by doing the following
SELECT
`someTable`.*
FROM `someTable`
INNER JOIN (
SELECT
`someTable`.`PrimaryKeyField`
#multiplier:=#multiplier*IF(`col1`<`col2`,0,1) AS counter
FROM `someTable` t, (SELECT #multiplier := 1) v
HAVING counter = 1
) t
ON scanQuery.`PrimaryKeyField` = `someTable`.`PrimaryKeyField`
Or possibly simply
SELECT
`someTable`.*
#multiplier:=#multiplier*IF(`col1`<`col2`,0,1) AS counter
FROM `someTable` t, (SELECT #multiplier := 1) v
HAVING counter = 1