Alternative to except in MySQL - mysql

I must write a Query like this in MySQL:
SELECT *
FROM Tab1
EXCEPT
SELECT *
FROM Tab1
WHERE int_attribute_of_Tab1>0
but MySQL doesn't support the keyword EXCEPT.
Is there a standard mode to use correctly another operator that simulate the except in MySQL?

You could use NOT IN
SELECT *
FROM Tab1
WHERE id NOT IN (
SELECT id
FROM Tab1
WHERE int_attribute_of_Tab1>0
)

Try this
SELECT *
FROM Tab1
WHERE [....] NOT EXISTS
(SELECT *
FROM Tab1
WHERE int_attribute_of_Tab1>0)

A couple of definitions
SqlServer https://learn.microsoft.com/en-us/sql/t-sql/language-elements/set-operators-except-and-intersect-transact-sql EXCEPT
Returns any distinct values from the query to the left of the EXCEPT operator that are not also returned from the right query.
PLsql https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries004.htm MINUS
statement combines results with the MINUS operator, which returns only unique rows returned by the first query but not by the second
A pedantic translation to mysql would be
SELECT distinct t1.*
FROM Tab1 as t1
left outer join
(SELECT *
FROM Tab1
WHERE int_attribute_of_Tab1>0) as t2 on t1.id = t2.id
where t2.id is null;
Assuming there is an id column, And I wouldn't like to use distinct on a lot of columns.

You can use multiple NOT IN operators combined with AND operators for multiple columns.
For example:
SELECT col1, col2 FROM table1 WHERE col1 NOT IN(SELECT col1 FROM table2) AND col2 NOT IN(SELECT col2 FROM table2)...;

Since MySQL version 8.0.31 update, the EXCEPT operator has become available to use in this DBMS. If you are allowed to update your MySQL version, you are free to use the notation:
SELECT * FROM Tab1
EXCEPT
SELECT * FROM Tab1
WHERE int_attribute_of_Tab1>0

If Tab1 has a primary key (f.e. ID) then you could use a NOT EXISTS to itself like this :
SELECT *
FROM Tab1 AS t1
WHERE NOT EXISTS (
SELECT 1
FROM Tab1 AS t2
WHERE t2.ID = t1.ID
AND t2.int_attribute_of_Tab1 > 0
)
But it's kinda pointless in this case.
And it's not what an EXCEPT/MINUS tries to do.
(excluding identical rows)
The question's query with the EXCEPT uses the same table twice.
So reversing that WHERE criteria on Tab1 would give the same results.
SELECT *
FROM Tab1
WHERE (int_attribute_of_Tab1 <= 0 OR int_attribute_of_Tab1 IS NULL)
If it were 2 different tables then this
SELECT t1col1, t1col2, t1col3
FROM Table1
EXCEPT
SELECT t2col4, t2col5, t2col6
FROM Table2
WHERE int_attribute_of_Tab1 > 0
Could be replaced by comparing each selected column
SELECT DISTINCT t1col1, t1col2, t1col3
FROM Table1 AS t1
WHERE NOT EXISTS (
SELECT 1
FROM Table1 AS t2
WHERE t2.t2col4 = t1.t1col1
AND t2.t2col5 = t1.t1col2
AND t2.t2col6 = t1.t1col3
AND t2.int_attribute_of_Tab1 > 0
)

Related

Mysql merging two queries into one

Trying to merge below two queries into one in the most "correct/efficient" way:
select id from TABLE1 where apple='green'
while{
select * from TABLE2 where id=[id from TABLE1 above]
while{
Eg query one will return a number of id's which in turn will return a number of rows in query two.
You can try to use EXISTS subquery
SELECT *
FROM TABLE2 t2
WHERE EXISTS(
SELECT 1
FROM TABLE1 t1
WHERE t1.apple='green' AND t1.id = t2.id
)

How to check every field in a table is nt substring of a field in another table

My scheme looks like:
I have two tables: table1, table2
table1 has one field: table1-name of type string.
table2 has one field: table2-name of type string.
I want to return all rows of table1-name that are NOT substring of any table2-name records. I did:
SELECT DISTINCT `table2-name`.`table2`
FROM `table2`, `table1`
WHERE `table2-name`.`table2` NOT IN (SELECT `table1-name` FROM `table1`)
LIMIT 100;
But this returns all table2-name that are not equal to table1-name. What I need is all table2-namethat are not sub-string of table2-name.
Example:
table1-name:aa.abc.com, bb.com, xyz.com
table2-name: abc.com, aaa.com, xyz.com
The query above will return:
abc.com
aaa.com
What I want to return is:
aaa.com
I do not want abc.com to be returned because it is a sub-string of aa.abc.com.
Can you correct my query?
Use NOT EXISTS for such conditions:
select *
from table1 t1
where not exists
(
select *
from table2 t2
where t2.`table2-name` like concat('%', t1.`table1-name`, '%')
);
BTW: You should avoid names like table2-name where you need quotes in order to use them. Use something like table2_name instead.
If table2 is not very big, I wonder how this would perform:
select t1.*
from table1 t1 cross join
(select group_concat(t2.name separator '|') as names
from table2 t2
) t2
where t1.name not regexp t2.names;
Or, equivalently:
select t1.*
from table1 t1 cross join
(select group_concat(t2.name) as names
from table2 t2
) t2
where find_in_set(t1.name, t2.names) = 0;
This assumes that t2.name does not have special characters (for regexp) or commas (for find_in_set()).
To check if something is a substring of something else, you would need to use either 'LIKE' (as shown below) or possibly 'REGEXP_LIKE'.
SELECT DISTINCT table2.*
FROM table2
WHERE NOT EXISTS (SELECT 1 FROM table1 where table1.table1name LIKE CONCAT('%',table2.table2name,'%') > 0)
LIMIT 100;
On another note
1 - your problem description is not consistent (you confuse table1 and table2 repeatedly), choosing a better name would likely help with that.
2 - as you will see, I've taken the liberty of renaming the columns to drop the '-' character.
Another version that will work:
SELECT DISTINCT table2.*
FROM table2
WHERE table2name NOT IN (SELECT table2.table2name FROM table1 where table1.table1name like CONCAT('%',table2.table2name,'%') > 0)
LIMIT 100;
Please check the SQLFiddle (I also copied Thorsten Kettner's version above in there after renaming tables/columns)

how to ignore where condition results and select remained results in sql server

I have a table with 17 records. I select rows by a where condition such as below query:
SELECT * FROM T1 WHERE (c1='AA' and c3=13)
2 records were the results of this query.
now i want to select the 15 records of table T1!!!
i add the not operator before the where condition like:
SELECT * FROM T1 WHERE not (c1='AA' and c3=13)
14 records were the results of this query. but the Table has 17 records
it's not possible to use EXCEPT clause, because this clause only selects distinct records.
What if i use EXISTS ?? for SQL Server
select * from t1 t
where not exists(
select * from t1 where (t.c1='AA' and t.c3=13)
)
In case Id is Duplicate then Use Row_number() function.
SELECT T1.* FROM T1
LEFT JOIN (SELECT * FROM T1 WHERE (c1='AA' AND c3=13)) AS T2
ON(T1.ID=T2.ID) WHERE T2.ID IS NULL;
Please try like this, EXCEPT Clause
SELECT DISTINCT * FROM
(
SELECT * FROM T1
EXCEPT
SELECT * FROM T1 WHERE (c1='AA' and c3=13)
)k
SELECT * FROM t1
WHERE PrimaryKey_Col not in (
SELECT PrimaryKey_Col FROM t1 WHERE t.c1='AA' and t.c3=13
);
Note : This query easily work Based on PrimaryKey

select only one of the identical rows (specific) between two tables in a union

i have have two identical tables
lets call them t1 and t2
and i want to show data from both of them BUT they may have identical rows (lets say these rows have the same id )
in that case i only want to get the row from table 1 and ignore the one from second table .
so
SELECT column_name(s) FROM t1 UNION SELECT column_name(s) FROM t2
but how should i handle duplicates ?
you mean this ?
select column1 , column2 from (
SELECT column1 , column2 FROM t1
UNION
SELECT column1 , column2 FROM t2
)t
group by column1
you will have distinct column1 here
If you want to remove duplicates from a SELECT result set, you could use the DISTINCT clause with a sub-query
SELECT DISTINCT * FROM (SELECT value FROM t1 UNION SELECT value FROM t2) AS S
Or better, you might use the UNION DISTINCT syntax:
SELECT value FROM t1 UNION DISTINCT SELECT value FROM t2;
BTW, for UNION the default is UNION DISTINCT (whereas for SELECT, SELECT ALL is the default), so this could be rewritten as:
-- without specifier UNION is implicitly DISTINCT
SELECT value FROM t1 UNION SELECT value FROM t2;
... which is in fact the query you proposed. What was wrong with that? It works with my test set: http://sqlfiddle.com/#!2/d4812/1
Maybe a sqlfeedle with your actual table content might help to provide a better answer.
Here is one way:
SELECT column_name(s)
FROM t1
UNION
SELECT column_name(s)
FROM t2
where not exists (select 1
from t1
where t1.col1 = t2.col1 and t1.col2 = t2.col2 and . . .
)

How to rewrite this SELECT query

I've been left with some code that looks like this:
SELECT DISTINCT ee.* FROM exp_extensions ee WHERE enabled = 'y'
Our db admin is screaming about the select all, and wants us to grab all the individual fields separately. I've never seen a SELECT DISTINCT * before; how would I rewrite that?
Option 1:
SELECT DISTINCT ee.extension_id, ee.class, ee.method, ee.hook, ee.settings, ee.priority, ee.version, ee.enabled FROM exp_extensions ee WHERE enabled = 'y'
Option 2:
SELECT DISTINCT (ee.extension_id, ee.class, ee.method, ee.hook, ee.settings, ee.priority, ee.version, ee.enabled) FROM exp_extensions ee WHERE enabled = 'y'
Or some other way entirely?
There is no difference between Option 1 or Option 2. Say you have a table that has one column col1 that has one row. All of these produce the same result:
SELECT DISTINCT * FROM t1
SELECT DISTINCT col1 FROM t1
SELECT DISTINCT (col1) FROM t1
SELECT * FROM t1
SELECT col1 FROM t1
SELECT (col1) FROM t1
All the * does is essentially expand to all available columns on the table.