I have a simple MYSQL query that unions two tables:
SELECT * FROM (
SELECT col1 AS col1A FROM table1
UNION
SELECT col1 AS col1B FROM table2
) AS t WHERE col1A <> col1B
I have a column called col1
in both tables and I need to select only rows that have a different value of that column so I select them as aliases. When I run this query I got:
Unknown column 'col1B' in 'where clause'
Table1 data:
col1
----
test
Table2 data:
col1
----
test
The query should return no rows as each value in col1 in table1 is equal to each value in col1 in table2 instead it returns that col1 in table2 is unknown although I select it as an alias
Why Error 1054 is being returned by OP query
The error that's being returned is because the name assigned to a column from the result of a UNION is taken from the first SELECT.
You can observe this by running a simple example:
SELECT 1 AS one
UNION
SELECT 2 AS two
The resultset returned by that query will contain a single column, the name assigned to the column will be one
, the column name from the first SELECT. This explains why you are getting the error from your query.
One way to return rows with no match
To return values of col1
from table1
which do not match any value in the col1
column from table2
...
one option to use an anti-join pattern...
SELECT t1.col1
FROM table1 t1
LEFT
JOIN table2 t2
ON t2.col1 = t1.col1
WHERE t2.col1 IS NULL
The LEFT JOIN
operation returns all rows from table1, along with any "matching" rows found in table2. The "trick" is the predicate in the WHERE clause... any "matching" rows from table2 will have a non-NULL value in col1. So, if we exclude all of the rows where we found a match, we're left with rows from table1 that didn't have a match.
If we want to get rows from table2
that don't have a "matching" row in table1
, we can do the same thing, just flipping the order of the tables.
If we combine the two sets, but only want a "distinct" list of "not matched" values, we can use the UNION
set operator:
SELECT t1.col1
FROM table1 t1
LEFT
JOIN table2 t2
ON t2.col1 = t1.col1
WHERE t2.col1 IS NULL
UNION
SELECT s2.col1
FROM table2 s2
LEFT
JOIN table1 s1
ON s1.col1 = s2.col1
WHERE s1.col1 IS NULL
--
Finding out which table the non-matched value is from
Sometimes, we want to know which query returned the value; we can get that by including a literal value as a discriminator in each query.
SELECT 'table1' AS src
, t1.col1
FROM table1 t1
LEFT
JOIN table2 t2
ON t2.col1 = t1.col1
WHERE t2.col1 IS NULL
UNION
SELECT 'table2' AS src
, s2.col1
FROM table2 s2
LEFT
JOIN table1 s1
ON s1.col1 = s2.col1
WHERE s1.col1 IS NULL
ORDER BY 2
A different (usually less performant) approach to finding non-matching rows
An entirely different approach, to returning an equivalent result, would be do something like this:
SELECT q.col1
FROM ( SELECT 't1' AS src, t1.col1 FROM table1 t1
UNION
SELECT 't2' AS src, t2.col1 FROM table2 t2
) q
GROUP BY q.col1
HAVING COUNT(DISTINCT q.src) < 2
ORDER BY q.col1
(The inline view q
will be "materialized" as a derived table, so this approach can be expensive for large sets, and this approach won't take advantage of indexes on col1
to perform the matching.) One other small difference between this and the anti-join approach: this will omit a col1 value of NULL if a NULL exists in both tables. Aside from that, the resultset is equivalent.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다