MySQL query delivers wrong result when using <> (not equal) in WHERE clause - mysql

I came accross a strange problem with a MySQL Query
SELECT COUNT(id) FROM members
100
SELECT COUNT(id) FROM members WHERE lastname = 'Smith'
20
SELECT COUNT(id) FROM members WHERE lastname <> 'Smith'
0
The problem is, that the last query (Members with lastname != 'Smith') returns 0.
If there are 100 members in total and 20 members named 'Smith', the number of member with other last names should be 80, shouldn't it?
I tried different version using <>, !=, enclosing Smith with ' or ". The result when using LIKE and NOT LIKE instead is the same.
How is this possible? It seems that I am missing something quite obvious, but what...?

because others are null
try this :
SELECT COUNT(id) FROM members WHERE IFNULL(lastname ,'--')<> 'Smith'
Example :
CREATE TABLE my_table
SELECT 'ersin' name FROM dual
union all
SELECT 'ersin' name FROM dual
union all
SELECT 'ersin' name FROM dual
union all
SELECT null name FROM dual
union all
SELECT null name FROM dual
union all
SELECT null name FROM dual;
select script:
select count(*) from my_table where IFNULL(name ,'--') <> 'ersin' ;
output:
count(*)
3

Related

Select rows with duplicate values that may be in different columns

I have a table of businesses, and each business can have up to 3 phone numbers. I want to find any duplicate phone numbers, but since the phone numbers are in different columns I don't think I can make the classic GROUP BY query work.
Sample data:
ID
Business_Name
phone_main
phone_mobile
phone_tollfree
1
John's Donuts
555-551-5555
555-551-5556
null
2
John's Bakery
555-551-5557
555-551-5555
null
3
SuperBake!
555-300-1005
null
555-551-5555
4
Grocery Fred
555-223-5511
555-334-5555
null
In this case I want to identify records 1, 2, and 3 as being the same. Simply identifying the phone number 555-551-5555 as a number with duplicates would be fine, as I can do a subquery or the calling program can use the phone number and send a new query getting all records with 555-551-5555 in any of the 3 phone columns.
This is on MariaDB if it matters.
Edit, (adding my current flailing attempt since someone seems to really want it):
Here's what I have right now:
SELECT ID, phone_main, phone_mobile, phone_tollfree
(
SELECT COUNT(*) FROM businesses b
WHERE (
phone IS NOT NULL AND (b.phone_mobile=phone OR b.tollfree=phone )
)
OR (
phone_mobile IS NOT NULL AND (b.phone=phone_mobile OR b.phone_tollfree=phone_mobile)
)
OR (
phone_tollfree IS NOT NULL AND (b.phone=phone_tollfree OR b.phone_mobile=phone_tollfree)
)
) cnt
from business HAVING cnt > 1
Problems with this:
It seems to be returning every row in my table.
It won't find duplicates within a single column.
How about uniting all the phone columns into one an then counting the reoccurrences?
I Didn't run the code but it might give you a direction...:
SELECT phone, COUNT(phone)
FROM (
SELECT phone_main as phone FROM SampleData
UNION ALL
(SELECT phone_mobile as phone FROM SampleData
ORDER BY City;
UNION ALL
SELECT phone_tollfree as phone FROM SampleData
ORDER BY City; and )
)
GROUP BY phone
E.g.:
SELECT DISTINCT x.*
FROM my_table x
JOIN my_table y
ON y.id <> x.id
AND
( y.phone_main IN(x.phone_main,x.phone_mobile,x.phone_tollfree)
OR y.phone_mobile IN(x.phone_main,x.phone_mobile,x.phone_tollfree)
OR y.phone_tollfree IN(x.phone_main,x.phone_mobile,x.phone_tollfree)
);
You can do:
with
l as (
select *, least(phone_main, phone_mobile, phone_tollfree) as p
from t
)
select *
from l
where p in (select p from l group by p having count(*) > 1)

I want to merge two tables [Tabl1] and [Tabl2] and show result by ID where [Tabl1].[names] = 'any string name'?

In my example where name like '' show all value tabl2 with tabl1
SELECT *
FROM
(SELECT
ID, names, NULL AS address, work, note
FROM
Tabl1
UNION
SELECT
ID, name, address, NULL, NULL
FROM
Tabl2) as x
ORDER BY
id, note DESC, address
With CTE_NAME(ID, names) --Column names for Temporary table
AS
(
SELECT ID , NAME FROM TABLE1
UNION
SELECT ID , NAME FROM TABLE2
)
SELECT * FROM CTE_NAME --SELECT or USE CTE temporary Table
WHERE name = "x"
ORDER BY ID
You'll need to use UNION to combine the results of two queries. In your case:
SELECT ID, names, NULL AS address, work, note
FROM Tabl1
GROUP BY names
UNION ALL
SELECT ID, name, address, NULL, NULL
FROM Tabl2
GROUP BY Tabl3
Note - If you use UNION ALL as in above, it's no slower than running the two queries separately as it does no duplicate-checking.

in sql how the dbms execute the query

In nor_employees table, when I execute the below query,no rows are selected.
SELECT lastname, firstname, employee_id
FROM nor_employees
WHERE employee_id NOT IN
(SELECT reports_to FROM NOR_EMPLOYEES);
for the below query it is getting.
SELECT lastname, firstname, employee_id
FROM nor_employees
WHERE employee_id NOT IN
(SELECT reports_to FROM NOR_EMPLOYEES where reports_to is not null);
can you explain why?
There is a 3 value logic.
NOT IN clause is translated to not equal, i.e.
select *
from table
where col not in (10,20 )
it is translated by interpreter to
select *
from table
where col <> 10 and col <> 20
In case, if one of values in the list null then we have col <> Null. It always False. As result no rows in result set

SELECT WHERE IN - mySQL

let's say I have the following Table:
ID, Name
1, John
2, Jim
3, Steve
4, Tom
I run the following query
SELECT Id FROM Table WHERE NAME IN ('John', 'Jim', 'Bill');
I want to get something like:
ID
1
2
NULL or 0
Is it possible?
How about this?
SELECT Id FROM Table WHERE NAME IN ('John', 'Jim', 'Bill')
UNION
SELECT null;
Start by creating a subquery of names you're looking for, then left join the subquery to your table:
SELECT myTable.ID
FROM (
SELECT 'John' AS Name
UNION SELECT 'Jim'
UNION SELECT 'Bill'
) NameList
LEFT JOIN myTable ON NameList.Name = myTable.Name
This will return null for each name that isn't found. To return a zero instead, just start the query with SELECT COALESCE(myTable.ID, 0) instead of SELECT myTable.ID.
There's a SQL Fiddle here.
The question is a bit confusing. "IN" is a valid operator in SQL and it means a match with any of the values (see here ):
SELECT Id FROM Table WHERE NAME IN ('John', 'Jim', 'Bill');
Is the same as:
SELECT Id FROM Table WHERE NAME = 'John' OR NAME = 'Jim' OR NAME = 'Bill';
In your answer you seem to want the replies for each of the values, in order. This is accomplished by joining the results with UNION ALL (only UNION eliminates duplicates and can change the order):
SELECT max(Id) FROM Table WHERE NAME = 'John' UNION ALL
SELECT max(Id) FROM Table WHERE NAME = 'Jim' UNION ALL
SELECT max(Id) FROM Table WHERE NAME = 'Bill';
The above will return 1 Id (the max) if there are matches and NULL if there are none (e.g. for Bill). Note that in general you can have more than one row matching some of the names in your list, I used "max" to select one, you may be better of in keeping the loop on the values outside the query or in using the (ID, Name) table in a join with other tables in your database, instead of making the list of ID and then using it.

Selecting DISTINCT where not null in MySQL

I've got a table that has, for example, ID and Name.
There are multiple rows that contain blank names, but there also can be multiple rows with the same name. I'd like to select all IDs, counting each name only once (DISTINCT), but selecting ALL of the blanks.
The following query naturally only selects ONE blank name. How can I select all the distinct names plus all of the blank names?
SELECT DISTINCT Name, ID
FROM TestTable
SELECT DISTINCT Name, ID FROM TestTable where Name <> ''
union all
SELECT Name, ID FROM TestTable where Name = ''
Only slight improvement I can think of would be:
SELECT DISTINCT Name, ID FROM TestTable where Name <> ''
union all
SELECT '', ID FROM TestTable where Name IS NULL OR Name = ''