I have a query ended with ORDER BY NOT EXISTS.
I am having an issue with NOT EXISTS to look at two columns from another table. The query works with col1, but not with col2
FROM
t1
JOIN t2 ON t1.id = t2.id
...
ORDER BY NOT EXISTS
(SELECT col1, col2
FROM t1
WHERE t1.id2 = t2.id2
AND MONTH(t1.date) = MONTH(CURDATE())
) DESC
Ok, Just testing it and found out the solution, that if i use
WHERE t1.id = t2.id
and instead of
WHERE t1.id2 = t2.id2
it worked. I told them to look at the current table id PK column and not the another table id FK and it worked.
I have an UPDATE and SELECT statement working in SQL however I am unable to replicate the same outcome in MYSQL.
I have a table (TBL1) with, say 4 columns:-
col1: registration (VARCHAR)
col2: date
col3: oldest date flag (values Y or blank)
col4: index (priamry key - auto-increment).
An ongoing process continues to add registrations and dates to the table. After a batch of additions any col3 'Y' flags will be removed and then an update process will set the col3 value = 'Y' for each the row where the registration has the oldest date.
Here is the SQL code, this works as expected after an earlier process removes any previous col3 'Y' values;-
UPDATE T1
SET T1.Col3 = 'Y'
SELECT FROM TBL1 AS T1
INNER JOIN ( SELECT Col1 AS REG, MIN(Col2) AS MINDATE
FROM TBL1
GROUP BY Col1) AS T2
ON T1.Col1 = T2.REG and T1.Col2 = T2.MINDATE
The result correctly recognises for each unique registration the oldest date and sets 'Y' in col3.
I need to replicate this process in MYSQL but after much effort I can't find a way to do this?
If you are just looking for the same logic, but with MySQL's update join syntax, then try this:
UPDATE TBL1 T1
INNER JOIN
(
SELECT Col1 AS REG, MIN(Col2) AS MINDATE
FROM TBL1
GROUP BY Col1
) AS T2
ON T1.Col1 = T2.REG and T1.Col2 = T2.MINDATE
SET T1.Col3 = 'Y';
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
I think you need to look up the appropriate usage of UNION. It will return all results from first query combined with all results from the second query. This results in a single dataset, with a single column (not col1 and col2), just col1 in this case.
Assuming you're trying to get all records in table1 that don't exist in table2, you can use NOT EXISTS:
SELECT col1
FROM table1 t1
WHERE NOT EXISTS (
SELECT 1
FROM table2 t2
WHERE t1.col1 = t2.col1
)
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.
If I have 2 tables and want to find if they have the same data, what is the most straightforward way to do it in MySQL?
I have read about doing a correlated subquery and UNION ALL but this query is about 2 pages (!) and can not really follow what it is doing. There must be an easier way.
Even if it is e.g. make MySQL copy the table data to files and do a vimdiff (I am not sure that this is even possible -is it?- just thinking out loud).
UPDATE
I am interested only in the table data and not structure. This is to clarify due to an ambiguous comment I made
If you just want to tell whether the tables are identical or not as efficiently as possible, use this query:
SELECT 1 FROM (
SELECT * FROM table1
UNION ALL
SELECT * FROM table2
) t
GROUP BY col1, col2, col3
HAVING count(*) = 1
LIMIT 1
List all the columns in GROUP BY to compare the entire table.
If the result is an empty set, the two tables are identical.
If you want to see the differences, use this query:
SELECT * FROM (
SELECT 'table1' tname, col1, col2, col3 FROM table1
UNION ALL
SELECT 'table2' tname, col1, col2, col3 FROM table2
) t
GROUP BY col1, col2, col3
HAVING count(*) = 1
List the same columns in the inner SELECT as in the GROUP BY, plus a column to distinguish the two tables.
Just throwing this out there, you could emulate a full outer join and then return the rows where just the right or the left side is null.
select t1.*
from table1 t1
LEFT OUTER JOIN table2 t2
ON t1.col1 = t2.col1
AND t1.col2 = t2.col2
AND ...
WHERE t2.id is null
UNION
select t2.*
from table2 t2
LEFT OUTER JOIN table1 t1
ON t2.col1 = t1.col1
AND t2.col2 = t1.col2
AND ...
WHERE t1.id is null
With the FULL OUTER JOIN you can show all rows where the other row is not available in the other table.
Use the following query:
SELECT c1 = cjoin AND c2 = cjoin equiv
FROM (SELECT COUNT(*) c1 FROM Table1) t1,
(SELECT COUNT(*) c2 FROM Table2) t2,
(SELECT COUNT(*) cjoin
FROM Table1 t1
JOIN Table2 t2
ON t1.col1 = t2.col1 AND t1.col2 = t2.col2 AND t1.col3 = t2.col3 ...) tjoin
Assuming the tables have a unique key, this will return equiv = 1 if the tables are equal. It doesn't show the differences, it's just a binary test.
I was reading SQL Cookbook from A.Molinaro, when I came across a solution.
It is based on to tables
emp(empno,ename,job,mgr,hiredate,sal,comm,deptno)
and a view
V
which has the same columns but different rows. The columns mgr and comm might be NULL, other columns not.
The solution in the book is very long and it does not show all differences, although this was the stated problem in 3.7.
I made up my solution which is shorter and shows all differences (means all rows which have different counts in the two tables).
select * from
# those which are contained in the (distinct) union of (col1,col2,...,coln, count) of both tables:
( select empno,ename,job,mgr,hiredate,comm,deptno, count(*) cnt from emp group by empno,ename,job,mgr,hiredate,comm,deptno
union
select empno,ename,job,mgr,hiredate,comm,deptno, count(*) cnt from V group by empno,ename,job,mgr,hiredate,comm,deptno
) as unionOfBoth
where (empno,ename,job,mgr,hiredate,comm,deptno,cnt)
not in
# those which are contained in the intersection of both tables with the equal number of counts:
( select e.empno,e.ename,e.job,e.mgr,e.hiredate,e.comm,e.deptno,e.cnt
from
(select empno, ename,job,mgr,hiredate,comm,deptno, count(*) cnt from emp group by empno,ename,job,mgr,hiredate,comm,deptno) e,
(select empno, ename,job,mgr,hiredate,comm,deptno, count(*) cnt from V group by empno,ename,job,mgr,hiredate,comm,deptno) v
where
e.empno = v.empno
and e.ename = v.ename
and e.job = v.job
and ifnull(e.mgr,0) = ifnull(v.mgr,0)
and e.hiredate = v.mgr
and e.deptno = v.deptno
and ifnull(e.comm,0) = ifnull(v.comm,0)
and e.cnt = v.cnt
);
Basically you count the distinct rows in both tables and do a union (not union all) to get the tmp.table unionBoth. Then you remove those rows, which both tables have in common.
Here two rows r1 from table t1 and r2 from table t2 are considered the same, if
(r1,count of r1 in t1) = (r2, count of r2 in t2), which is equivalent to r1=r2 (on all columns) and (count of r1 in t1) = (count of r2 in t2).
If the tables are small enough, you can export both tables as csv files and then copy one of the tables and paste them side-by-side with the other table. You can just go row by row and see if the outputs are the same that way.
I'm not a SQL guy, and I've just tried every JOIN MySQL offers.
I primarily need data from view1 using WHERE, ORDER BY, LIMIT with offset (the data is incorrect without those conditions.)
view1 is not limited by view2
Data also needs to be pulled from view2, but view2 has its' own WHERE (or whatever's best) condition
view2 may not have corresponding data, but it shouldn't be grabbed without being linked to view1 (NULLs are just fine!)
I'll just give you the two SELECTs that work for me rather than the hashes I've come up with.
For view1:
SELECT * FROM view1
WHERE column1 IS NULL OR column1 = 1
ORDER BY dateColumn DESC LIMIT index1, count1;
(index1 and count1 are INs i use for a stored proc)
For view2:
SELECT * FROM table2
WHERE column1 = ? AND table1_id IN (
SELECT id FROM view1
WHERE column1 IS NULL OR column1 = 1
ORDER BY dateColumn DESC LIMIT index1, count1
)
GROUP BY table1_id
(? is any arbitrary value i put in)
I'm at wits end. I have no idea how to fuse these two.
Specifics
Please note that the IN for view2 is almost identical to the view1 query. Thanks!
You can write a subquery for table2 and add WHERE clause there, also you can add WHERE clause at the ent of the query -
SELECT * FROM table2 t2
JOIN (
SELECT id FROM table1
WHERE column1 IS NULL OR column1 = 1
ORDER BY dateColumn DESC
LIMIT index1, count1
) t1
ON t1.id = t2.table1_id
WHERE
t2.column1 = ?
GROUP BY
t2.table1_id
In this example I used JOIN instead of WHERE IN condition.
How about this query:
Select t1.id
FROM table1 t1
JOIN table2 t2 ON t1.id = t2.table1_id
WHERE t1.column1 IS NULL OR t1.column1 = 1
i think it should help you
Select TableName1.id
FROM TableName1
JOIN TableName2 ON TableName1.id = TableName2.id
WHERE TableName1.column1 IS NULL OR TableName1.column1 = 1