I have the following question.
I have to columns and I want for each unique entry the first column the most frequent element of the second column. An Example would be:
COL A COL B
1 a
2 c
2 c
1 a
1 b
2 d
The query should output:
Col A COL B
1 a
2 c
Given this sample data:
CREATE TABLE t
(`a` int, `b` varchar(1))
;
INSERT INTO t
(`a`, `b`)
VALUES
(1, 'a'),
(2, 'c'),
(2, 'c'),
(1, 'a'),
(1, 'b'),
(2, 'd')
;
you first have to get the count for each with a query like this:
SELECT
a, b,
COUNT(*) AS amount
FROM
t
GROUP BY
a, b
Then you can use this query as a subquery to get the rows where a certain column holds the maximum. There's a nice article about this in the manual: The Rows Holding the Group-wise Maximum of a Certain Column
Choosing for example the last method described in said article, your final query would be this:
SELECT sq1.a, sq1.b FROM
(
SELECT
a, b,
COUNT(*) AS amount
FROM
t
GROUP BY
a, b
) sq1
LEFT JOIN
(
SELECT
a, b,
COUNT(*) AS amount
FROM
t
GROUP BY
a, b
) sq2 ON sq1.a = sq2.a AND sq1.amount < sq2.amount
WHERE sq2.amount IS NULL;
With this result:
+------+------+
| a | b |
+------+------+
| 1 | a |
| 2 | c |
+------+------+
Using a subselect in the SELECT clause is a simple way to solve your problem:
SELECT ColA, (SELECT ColB
FROM yourtable i
WHERE i.ColA = o.ColA
GROUP BY ColB
ORDER BY COUNT(*) DESC
LIMIT 1) AS ColB
FROM yourtable o
GROUP BY ColA;
o is just an alias for the outer query, i for the inner query. They're needed for the WHERE clause to work.
The above query is a result of the following query to find the most common occurence of ColB with a given ColA:
SELECT ColB
FROM yourtable
WHERE ColA = 1 -- Replace 1; this is where the magic happens in the above query
GROUP BY ColB
ORDER BY COUNT(*) DESC
LIMIT 1
you have to create My Sql function for this let say you function name is getMaxOccr so it will look like
CREATE FUNCTION `getMaxOccr`(val INT)
RETURNS varchar(25) CHARSET latin1
BEGIN
DECLARE answer VARCHAR(25) DEFAULT '';
SELECT colb FROM `tablename`
WHERE cola = val
ORDER BY COUNT(colb)
DESC INTO answer;
RETURN answer;
END
Once this function is created than you simply have to call
SELECT cola,getMaxOccr(cola) from tablename GROUP BY cola
this will give you the list with what you are looking for hope this helps
Related
I have three tables.
For each "id" value, I would like the sum of the col1 values, the sum of col2 values & the sum of col3 values listed separately. I am not summing across tables.
table a
num | id | col1
================
1 100 0
2 100 1
3 100 0
1 101 1
2 101 1
3 101 0
table b
idx | id | col2
=================
1 100 20
2 100 20
3 100 20
4 101 100
5 101 100
table c
idx | id | col3
==============================
1 100 1
2 100 1
3 100 1
4 101 10
5 101 1
I would like the results to look like this,
ID | sum_col1 | sum_col2 | sum_col3
====================================
100 1 60 3
101 2 200 11
Here is my query which runs too long and then times out. My tables are about 25,000 rows.
SELECT a.id as id,
SUM(a.col1) as sum_col1,
SUM(b.col2) as sum_col2,
SUM(c.col3) as sum_col3
FROM a, b, c
WHERE a.id=b.id
AND a=id=c.id
GROUP by id
Order by id desc
The number of rows in each table may be different, but the range of "id" values in each table is the same.
This appears to be a similar question, but I can't make it work,
Mysql join two tables sum, where and group by
Here is a solution based on your data. Issue with your query is that you were joining tables on a non-unique column resulting in Cartesian product.
Data
DROP TABLE IF EXISTS A;
CREATE TABLE A
(num int,
id int,
col1 int);
INSERT INTO A VALUES (1, 100, 0);
INSERT INTO A VALUES (2, 100, 1);
INSERT INTO A VALUES (3, 100, 0);
INSERT INTO A VALUES (1, 101, 1);
INSERT INTO A VALUES (2, 101, 1);
INSERT INTO A VALUES (3 , 101, 0);
DROP TABLE IF EXISTS B;
CREATE TABLE B
(idx int,
id int,
col2 int);
INSERT INTO B VALUES (1, 100, 20);
INSERT INTO B VALUES (2, 100, 20);
INSERT INTO B VALUES (3, 100, 20);
INSERT INTO B VALUES (4, 101, 100);
INSERT INTO B VALUES (5, 101, 100);
DROP TABLE IF EXISTS C;
CREATE TABLE C
(idx int,
id int,
col3 int);
INSERT INTO C VALUES (1, 100, 1);
INSERT INTO C VALUES (2, 100, 1);
INSERT INTO C VALUES (3, 100, 1);
INSERT INTO C VALUES (4, 101, 10);
INSERT INTO C VALUES (5, 101, 1);
Solution
SELECT a_sum.id, col1_sum, col2_sum, col3_sum
FROM (SELECT id, SUM(col1) AS col1_sum
FROM a
GROUP BY id ) a_sum
JOIN
(SELECT id, SUM(col2) AS col2_sum
FROM b
GROUP BY id ) b_sum
ON (a_sum.id = b_sum.id)
JOIN
(SELECT id, SUM(col3) AS col3_sum
FROM c
GROUP BY id ) c_sum
ON (a_sum.id = c_sum.id);
Result is as expected
Note: Do outer joins if an id doesnt have to be present in all three tables.
Maybe this will do?
Haven't got a chance to run it, but i think it can do the job.
SELECT sumA.id, sumA.sumCol1, sumB.sumCol2, sumC.sumCol3
FROM
(SELECT id, SUM(col1) AS sumCol1 FROM a GROUP BY id ORDER BY id ASC) AS sumA
JOIN (SELECT id, SUM(col2) AS sumCol2 FROM b GROUP BY id ORDER BY id ASC) AS sumB ON sumB.id = sumA.id
JOIN (SELECT id, SUM(col3) AS sumCol3 FROM c GROUP BY id ORDER BY id ASC) AS sumC ON sumC.id = sumB.id
;
EDIT
SELECT IF(sumA.id IS NOT NULL, sumA.id, IF(sumB.id IS NOT NULL, sumB.id, IF(sumC.id IS NOT NULL, sumC.id,''))),,
sumA.sumCol1, sumB.sumCol2, sumC.sumCol3
FROM
(SELECT id, SUM(col1) AS sumCol1 FROM a GROUP BY id ORDER BY id ASC) AS sumA
OUTER JOIN (SELECT id, SUM(col2) AS sumCol2 FROM b GROUP BY id ORDER BY id ASC) AS sumB ON sumB.id = sumA.id
OUTER JOIN (SELECT id, SUM(col3) AS sumCol3 FROM c GROUP BY id ORDER BY id ASC) AS sumC ON sumC.id = sumB.id
;
I would do the summing first, then union the results, then pivot them round:
SELECT
id,
MAX(CASE WHEN which = 'a' then sumof end) as sum_a,
MAX(CASE WHEN which = 'b' then sumof end) as sum_b,
MAX(CASE WHEN which = 'c' then sumof end) as sum_c
FROM
(
SELECT id, sum(col1) as sumof, 'a' as which FROM a GROUP BY id
UNION ALL
SELECT id, sum(col2) as sumof, 'b' as which FROM b GROUP BY id
UNION ALL
SELECT id, sum(col3) as sumof, 'c' as which FROM c GROUP BY id
) a
GROUP BY id
You could also union, then sum:
SELECT
id,
SUM(CASE WHEN which = 'a' then v end) as sum_a,
SUM(CASE WHEN which = 'b' then v end) as sum_b,
SUM(CASE WHEN which = 'c' then v end) as sum_c
FROM
(
SELECT id, col1 as v, 'a' as which FROM a GROUP BY id
UNION ALL
SELECT id, col2 as v, 'b' as which FROM b GROUP BY id
UNION ALL
SELECT id, col3 as v, 'c' as which FROM c GROUP BY id
) a
GROUP BY id
You cant easily use a join, unless all tables have all values of ID, in which case I'd say you can sum them as subqueries and then join the results together.. But if one of your tables suddenly lacks an id value that the other two tables have, that row disappears from your results (unless you use full outer join and some really ugly coalescing in your ON clause)
Using union in this case will give you a more missing-value-tolerant result set, as it can cope with missing values of ID in any table. Thus, we union the tables together into one dataset, but use a constant to track which table the value came from, that way we can pick it out into its own summation later
If any id value is not present in any table, then the sum for that column will be null. If you want it to be 0, you can change the MAX to SUM or wrap the MAX in a COALESCE
x = doesn't matter
table A
0 row0
1 row1
2 row2
table B
0 x
1 x
0 X
2 X
2 X
0 x
there are in this example 3 rows of 0, 2 rows of 2 and 1 row 1.
i want to get for example the two rows who has the highest count of rows.
desired result:
0 row0 ==> because 3 rows in b is the highest amount.
2 row2 ==> because 2 rows in b is the second highest amount.
my attempt so far:
SELECT Id, Name FROM A
WHERE Id =
(
SELECT IdB FROM B
GROUP BY IdB
ORDER BY count(IdB) DESC
LIMIT 2
)
edit: i use mysql
thanks
You want to JOIN your tables together by id:
SELECT
A.id,
A.name
FROM
A join
B on A.id = B.id
GROUP BY
A.name
ORDER BY
count(B.id) desc
LIMIT 2
SQLFIDDLE
That will return an output that matches your example above.
Not sure how you want to handle ties.
What this does is JOIN (learn more about joins) the two tables together based on your ID's then aggregate the results counting the occurrences of B.IDB and displaying that count along with the name from table A
SELECT A.Name, count(B.IDB) cnt
FROM A
INNER JOIN IDB
on A.ID = B.IDB
GROUP BY A.Name
ORDER BY count(B.IDB) desc
LIMIT 2
But with your example this should return
Name cnt
row0 3
row2 2
-- Sample table
-- table A schema
create table A (id int, name varchar(10))
insert into A
values (0, 'row0')
insert into A
values (1, 'row1')
insert into A
values (2, 'row2')
select * from A
-- table A schema
create table B (id int, name varchar(10))
insert into B
values (0, 'X')
insert into B
values (0, 'X')
insert into B
values (0, 'X')
insert into B
values (0, 'X')
insert into B
values (1, 'X')
insert into B
values (2, 'X')
insert into B
values (2, 'X')
insert into B
values (2, 'X')
insert into B
values (2, 'X')
insert into B
values (2, 'X')
insert into B
values (2, 'X')
select * from B
--Query
select Top 2 A.name, count(B.id) from A
inner join B on A.id = b.id
group by A.name
order by count(A.name) desc
You can try ;
select a.name, b.count
from A a,
(select idB, count(idB) count from B group by idB) b
where a.id = b.idB
and count > 1
Please take a look at this fiddle.
I'm working on a search filter select box and I want to insert the field names of a table as rows.
Here's the table schemea:
CREATE TABLE general
(`ID` int, `letter` varchar(21), `double-letters` varchar(21))
;
INSERT INTO general
(`ID`,`letter`,`double-letters`)
VALUES
(1, 'A','BB'),
(2, 'A','CC'),
(3, 'C','BB'),
(4, 'D','DD'),
(5, 'D','EE'),
(6, 'F','TT'),
(7, 'G','UU'),
(8, 'G','ZZ'),
(9, 'I','UU')
;
CREATE TABLE options
(`ID` int, `options` varchar(15))
;
INSERT INTO options
(`ID`,`options`)
VALUES
(1, 'letter'),
(2, 'double-letters')
;
The ID field in options table acts as a foreign key, and I want to get an output like the following and insert into a new table:
id field value
1 1 A
2 1 C
3 1 D
4 1 F
5 1 G
6 1 I
7 2 BB
8 2 CC
9 2 DD
10 2 EE
11 2 TT
12 2 UU
13 2 ZZ
My failed attempt:
select DISTINCT(a.letter),'letter' AS field
from general a
INNER JOIN
options b ON b.options = field
union all
select DISTINCT(a.double-letters), 'double-letters' AS field
from general a
INNER JOIN
options b ON b.options = field
Pretty sure you want this:
select distinct a.letter, 'letter' AS field
from general a
cross JOIN options b
where b.options = 'letter'
union all
select distinct a.`double-letters`, 'double-letters' AS field
from general a
cross JOIN options b
where b.options = 'double-letters'
Fiddle: http://sqlfiddle.com/#!2/bbf0b/18/0
A couple to things to point out, you can't join on a column alias. Because that column you're aliasing is a literal that you're selecting you can specify that literal as criteria in the WHERE clause.
You're not really joining on anything between GENERAL and OPTIONS, so what you really want is a CROSS JOIN; the criteria that you're putting into the ON clause actually belongs in the WHERE clause.
I just made this query on Oracle.
It works and produces the output you described :
SELECT ID, CASE WHEN LENGTH(VALUE)=2THEN 2 ELSE 1 END AS FIELD, VALUE
FROM (
SELECT rownum AS ID, letter AS VALUE FROM (SELECT DISTINCT letter FROM general ORDER BY letter)
UNION
SELECT (SELECT COUNT(DISTINCT LETTER) FROM general) +rownum AS ID, double_letters AS VALUE
FROM (
SELECT DISTINCT double_letters FROM general ORDER BY double_letters)
)
It should also run on Mysql.
I did not used the options table. I do not understand his role. And for this example, and this type of output it seems unnecessary
Hope this could help you to.
I have to combine these two mySQL queries into one. I duplicated a solution and used it on a join table. I am querying a join table that has two columns (labeled "to_" and "from_"). Both 'to_' and 'from_' hold an id number for the same table. I need to combine these queries in such a way that I get results based on: [('from_' + 'to_') > 3], where 'from_' and 'to_' have the same value (i.e., they refer to the same id).
$query = "select * from nodes where nodeID in (
select to_ from joinTable group by to_ having count(*) > 3
)";
...
$query = "select * from nodes where nodeID in (
select from_ from joinTable group by from_ having count(*) > 3
)";
Acknowledgement: I'm using a query based very closely on a solution 'Mr E' helped me with earlier.
You can try (see important notice at the last paragraph regarding to_ and from_ matching requirements):
SELECT X.to_, COUNT(*)
FROM joinTable X, joinTable Y
WHERE
X.to_ = Y.from_
GROUP BY X.to_
HAVING COUNT(*) > 2
Or
SELECT X.to_, COUNT(*)
FROM joinTable X LEFT JOIN joinTable Y ON X.to_ = Y.from_
GROUP BY X.to_
HAVING COUNT(*) > 2
Using Mr E's test data:
CREATE TABLE `foo` (
`id` int(1) DEFAULT NULL,
`to_` varchar(5) DEFAULT NULL,
`from_` varchar(5) DEFAULT NULL
);
INSERT INTO `foo` VALUES (1,'A','B'),(2,'B','A'),(3,'B','C'),(4,'X','C'),(4,'X','B');
It will work, half-way, by issuing:
SELECT X.to_, Y.from_
FROM foo X LEFT JOIN foo Y ON X.to_ = Y.from_
which will then yield:
mysql> SELECT X.to_, Y.from_ /*--, COUNT(*) */
-> FROM foo X LEFT JOIN foo Y ON X.to_ = Y.from_;
+------+-------+
| to_ | from_ |
+------+-------+
| A | A |
| B | B |
| B | B |
| B | B |
| B | B |
| X | NULL |
| X | NULL |
+------+-------+
7 rows in set (0.00 sec)
and by running in full:
mysql> SELECT X.to_, COUNT(*)
-> FROM foo X LEFT JOIN foo Y ON X.to_ = Y.from_
-> GROUP BY X.to_
-> HAVING COUNT(*) > 2;
+------+----------+
| to_ | COUNT(*) |
+------+----------+
| B | 4 |
+------+----------+
Basically, join the table with itself and then generate an N:N list of matching records from both tables where to_ and from_ match (whether or not on the same row), then work with a single column and aggregate its values for the final COUNT(*).
And, most importantly, why have I lowered the number on the HAVING COUNT(*) from 3 to 2? The N:N relationship will issue N1 * N2 records (where N1 is the count of matching records on the first table and N2 on the second). So if the lower bound is three, we can only have over 3 records on these two tables by having one record in one of them and then 3 on the other (in whatever order) or 2 in one and 2 on the other (and then up from there) - otherwise there will be no matches on the to_ and from_ fields and this is something I am not sure about - whether the OP wants only records whose values appear on both fields or if having a COUNT(*) from a single side would suffice. If the latter is the case, however, I don't see any other option apart from separating the queries to deal with each column individually, as some people already have posted since that's an isolated sum we're dealing with. This will be slow if running against large tables.
SELECT * FROM(
SELECT nodeID, to_, count(*) cto_ FROM joinTable jta GROUP BY to_
OUTER JOIN
SELECT from_, count(*) cfrom_ FROM joinTable jtb GROUP BY from_
ON jta.nodeID = jtb.nodeID
) WHERE ((cto_ + cfrom) > 3) as tableA
INNER JOIN
node
ON node.nodeID = tableA.nodeID
I haven't tested to make sure this code compiles and runs but I think that's generally the right direction for the answer to what you want--
first get the count of to's from the to table
then get the count of from's from the from table
finally put the addition in the criteria for the two tables.
As long as the outer join is on same nodeID's it should only have one entry per nodeID, if I understand my code right.
OK, I ran it through a database I had handy, here's actual code that works on my database (change the names for yours of course)
SELECT * FROM (
SELECT * FROM
(
SELECT ticket_id, author_uid, count(*) cto_
FROM strato_ticket GROUP BY author_uid
) as jta
LEFT JOIN
(
SELECT ticket_id as tid, uid, count(*) cfrom_
FROM strato_ticket GROUP BY uid
) as jtb
ON jta.ticket_id = jtb.tid
WHERE ((cto_ + cfrom_) > 3)
) as jt
INNER JOIN strato_invite
ON strato_invite.ticket_id = jt.tid
It's not pretty, but:
select * from nodes where nodeID in (
select x from (
select to_ as x, count(*) as num
from joinTable group by to_
union all
select from_ as x, count(*) as num
from joinTable group by from_
) as temp_table
group by x having sum(num) > 3;
)
Doesn't seem to work for the OP. All I can say is "works on my machine" - here's the data and exact query I used:
CREATE TABLE `foo` (
`id` int(1) DEFAULT NULL,
`to_` varchar(5) DEFAULT NULL,
`from_` varchar(5) DEFAULT NULL
);
INSERT INTO `foo` VALUES (1,'A','B'),(2,'B','A'),(3,'B','C'),(4,'X','C'),(4,'X','B');
The query:
select x from (
select to_ as x, count(*) as num
from foo group by to_
union all
select from_ as x, count(*) as num
from foo group by from_
) as temp_table
group by x having sum(num) > 3;
I need to implement the following query in MySQL.
(select * from emovis_reporting where (id=3 and cut_name= '全プロセス' and cut_name='恐慌') )
intersect
( select * from emovis_reporting where (id=3) and ( cut_name='全プロセス' or cut_name='恐慌') )
I know that intersect is not in MySQL. So I need another way.
Please guide me.
Microsoft SQL Server's INTERSECT "returns any distinct values that are returned by both the query on the left and right sides of the INTERSECT operand" This is different from a standard INNER JOIN or WHERE EXISTS query.
SQL Server
CREATE TABLE table_a (
id INT PRIMARY KEY,
value VARCHAR(255)
);
CREATE TABLE table_b (
id INT PRIMARY KEY,
value VARCHAR(255)
);
INSERT INTO table_a VALUES (1, 'A'), (2, 'B'), (3, 'B');
INSERT INTO table_b VALUES (1, 'B');
SELECT value FROM table_a
INTERSECT
SELECT value FROM table_b
value
-----
B
(1 rows affected)
MySQL
CREATE TABLE `table_a` (
`id` INT NOT NULL AUTO_INCREMENT,
`value` varchar(255),
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `table_b` LIKE `table_a`;
INSERT INTO table_a VALUES (1, 'A'), (2, 'B'), (3, 'B');
INSERT INTO table_b VALUES (1, 'B');
SELECT value FROM table_a
INNER JOIN table_b
USING (value);
+-------+
| value |
+-------+
| B |
| B |
+-------+
2 rows in set (0.00 sec)
SELECT value FROM table_a
WHERE (value) IN
(SELECT value FROM table_b);
+-------+
| value |
+-------+
| B |
| B |
+-------+
With this particular question, the id column is involved, so duplicate values will not be returned, but for the sake of completeness, here's a MySQL alternative using INNER JOIN and DISTINCT:
SELECT DISTINCT value FROM table_a
INNER JOIN table_b
USING (value);
+-------+
| value |
+-------+
| B |
+-------+
And another example using WHERE ... IN and DISTINCT:
SELECT DISTINCT value FROM table_a
WHERE (value) IN
(SELECT value FROM table_b);
+-------+
| value |
+-------+
| B |
+-------+
There is a more effective way of generating an intersect, by using UNION ALL and GROUP BY. Performances are twice better according to my tests on large datasets.
Example:
SELECT t1.value from (
(SELECT DISTINCT value FROM table_a)
UNION ALL
(SELECT DISTINCT value FROM table_b)
) AS t1 GROUP BY value HAVING count(*) >= 2;
It is more effective, because with the INNER JOIN solution, MySQL will look up for the results of the first query, then for each row, look up for the result in the second query. With the UNION ALL-GROUP BY solution, it will query results of the first query, results of the second query, then group the results all together at once.
Your query would always return an empty recordset since cut_name= '全プロセス' and cut_name='恐慌' will never evaluate to true.
In general, INTERSECT in MySQL should be emulated like this:
SELECT *
FROM mytable m
WHERE EXISTS
(
SELECT NULL
FROM othertable o
WHERE (o.col1 = m.col1 OR (m.col1 IS NULL AND o.col1 IS NULL))
AND (o.col2 = m.col2 OR (m.col2 IS NULL AND o.col2 IS NULL))
AND (o.col3 = m.col3 OR (m.col3 IS NULL AND o.col3 IS NULL))
)
If both your tables have columns marked as NOT NULL, you can omit the IS NULL parts and rewrite the query with a slightly more efficient IN:
SELECT *
FROM mytable m
WHERE (col1, col2, col3) IN
(
SELECT col1, col2, col3
FROM othertable o
)
I just checked it in MySQL 5.7 and am really surprised how no one offered a simple answer: NATURAL JOIN
When the tables or (select outcome) have IDENTICAL columns, you can use NATURAL JOIN as a way to find intersection:
For example:
table1:
id, name, jobid
'1', 'John', '1'
'2', 'Jack', '3'
'3', 'Adam', '2'
'4', 'Bill', '6'
table2:
id, name, jobid
'1', 'John', '1'
'2', 'Jack', '3'
'3', 'Adam', '2'
'4', 'Bill', '5'
'5', 'Max', '6'
And here is the query:
SELECT * FROM table1 NATURAL JOIN table2;
Query Result:
id, name, jobid
'1', 'John', '1'
'2', 'Jack', '3'
'3', 'Adam', '2'
For completeness here is another method for emulating INTERSECT. Note that the IN (SELECT ...) form suggested in other answers is generally more efficient.
Generally for a table called mytable with a primary key called id:
SELECT id
FROM mytable AS a
INNER JOIN mytable AS b ON a.id = b.id
WHERE
(a.col1 = "someval")
AND
(b.col1 = "someotherval")
(Note that if you use SELECT * with this query you will get twice as many columns as are defined in mytable, this is because INNER JOIN generates a Cartesian product)
The INNER JOIN here generates every permutation of row-pairs from your table. That means every combination of rows is generated, in every possible order. The WHERE clause then filters the a side of the pair, then the b side. The result is that only rows which satisfy both conditions are returned, just like intersection two queries would do.
Starting from MySQL 8.0.31 the INTERSECT is natively supported.
INTERSECT Clause:
SELECT ...
INTERSECT [ALL | DISTINCT] SELECT ...
[INTERSECT [ALL | DISTINCT] SELECT ...]
INTERSECT limits the result from multiple SELECT statements to those rows which are common to all.
Sample:
SELECT 1 AS col
INTERSECT
SELECT 1 AS col;
-- output
1
Break your problem in 2 statements: firstly, you want to select all if
(id=3 and cut_name= '全プロセス' and cut_name='恐慌')
is true . Secondly, you want to select all if
(id=3) and ( cut_name='全プロセス' or cut_name='恐慌')
is true. So, we will join both by OR because we want to select all if anyone of them is true.
select * from emovis_reporting
where (id=3 and cut_name= '全プロセス' and cut_name='恐慌') OR
( (id=3) and ( cut_name='全プロセス' or cut_name='恐慌') )
AFAIR, MySQL implements INTERSECT through INNER JOIN.
SELECT
campo1,
campo2,
campo3,
campo4
FROM tabela1
WHERE CONCAT(campo1,campo2,campo3,IF(campo4 IS NULL,'',campo4))
NOT IN
(SELECT CONCAT(campo1,campo2,campo3,IF(campo4 IS NULL,'',campo4))
FROM tabela2);