Comparing one table against another in MySQL - php

Guys, I have two basic tables (id, first_name).
I want to run table 1 against table 2, delete duplicates, and spit out the cleansed version of table 1.
What's the easiest way to do this with PHP/MySQL?
Thanks.

This will delete all records from t1 that also exist in t2, leaving you with a stripped-down t1, but possibly with records in t2 that don't exist in t1:
DELETE FROM table1 t1
WHERE t1.id IN
(SELECT id from table2 t2
WHERE t2.id = t1.id AND t2.first_name = t1.first_name
)
*You may want to consider using EXISTS instead of IN, as per Brian Hooper's suggestion.
This will combine the two tables into a third table (t3), removing duplicates along the way:
SELECT * INTO t3
FROM t1 UNION SELECT * FROM t2
That will work for SQL Server (definitely) and MySQL (I think) but MySQL supports CREATE TABLE table_name AS select-statement, so you could use:
CREATE TABLE t3 AS
(SELECT * FROM t1 UNION DISTINCT SELECT * FROM t2)
*The DISTINCT keyword is optional - it's the default behaviour

DELETE FROM table1 t1
WHERE EXISTS (SELECT *
FROM table2 t2
WHERE t2.id = t1.id AND
t2.first_name = t1.first_name);
I'd prefer the exists to IN which I have had trouble with in the past, with it taking a long time.

Why not use
DELETE FROM table1 WHERE first_name IN (SELECT first_name from table2)
?
Correct me if I missed something.

This is without using subquery (not tested):
DELETE t1
FROM table1 t1
JOIN table2 t2
ON t2.id = t1.id
AND t2.first_name = t1.first_name

Related

Is it possible to select all rows from table 1 and each row meta data from table 2 in a single query?

I'm building a small CRM, I want to know if there's a way to actually bring all rows from table 1 but also in the same result, each row's meta data from table 2, let's say tasks t2.
Right now I'm using 2 queries, one to bring all rows from t1, then in a loop I select all rows from t2 if there's a match on the t1_id I push to the existing array the data.
t1
-------------------
id
number
created_at
updated_at
t2
-------------------
id
t1_id
something
created_at
updated_at
This may solve you problem :
SELECT *
FROM t1
LEFT JOIN t2 ON t1.id = t2.t1_id
I think the best is to use a group_concat but there is other ways :
SELECT t1.id,
t1.number,
t1.created_at,
t1.updated_at
GROUP_CONCAT(DISCTINCT t2.something) as meta
FROM t1
LEFT JOIN t2 on t1.id = t2.t1_id
GROUP BY t1.id,
t1.number,
t1.created_at,
t1.updated_at

Mysql Select All from one table, and some from another table Using Aliases

I'm posting this question because I did manage to find a similar question, but they weren't using aliases.
I have two tables - I want to grab everything from table1 and just grab the user_name and Team from table2.
My original query is grabbing everything from table2
SELECT *
FROM qabin.allqas t1
JOIN login.users t2
ON (t1.Submitter = t2.user_name)
WHERE t1.Status='Complete'
That's all well and good and works fine, but I would like to just get the user_name and the Team
To make things more interesting, they are in different databases, though it hasn't been an issue.
One is in the qabin database and the other is in the login database.
I have tried:
SELECT
qabin.allqas.* AS t1,
login.users.Team,
login.users.user_name
JOIN login.users t2
ON (t1.Submitter = t2.user_name)
WHERE t1.Status='Complete'
I need the t1 and t2 aliases because they are used elsewhere for building a larger query string.
Thanks in advance!
Why not use a subquery?
SELECT *
FROM qabin.allqas t1
JOIN (SELECT user_name, Team FROM login.users) t2
ON (t1.Submitter = t2.user_name)
WHERE t1.Status='Complete'
You cant use one alias (t1) for a set of columns. I guess what you are looking for is something like:
SELECT t1.*, t2.team, t2.user_name
FROM qabin.allqas t1
JOIN login.users t2
ON (t1.Submitter = t2.user_name)
WHERE t1.Status='Complete'
I would recommend using the real column names from t1 instead of t1.*
Try This query :
SELECT t1.*, t2.user_name, t2.Team
FROM qabin.allqas t1
JOIN login.users t2
ON t1.Submitter 1= t2.user_name
WHERE t1.Status='Complete'

PDO JOIN LEFT - fetch result - no result [duplicate]

I'm doing some maintenance work on a database application and I've discovered that, joy of joys, even though values from one table are being used in the style of foreign keys, there's no foreign key constraints on the tables.
I'm trying to add FK constraints on these columns, but I'm finding that, because there's already a whole load of bad data in the tables from previous errors which have been naively corrected, I need to find the rows which don't match up to the other table and then delete them.
I've found some examples of this kind of query on the web, but they all seem to provide examples rather than explanations, and I don't understand why they work.
Can someone explain to me how to construct a query which returns all the rows with no matches in another table, and what it's doing, so that I can make these queries myself, rather than coming running to SO for every table in this mess that has no FK constraints?
Here's a simple query:
SELECT t1.ID
FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.ID = t2.ID
WHERE t2.ID IS NULL
The key points are:
LEFT JOIN is used; this will return ALL rows from Table1, regardless of whether or not there is a matching row in Table2.
The WHERE t2.ID IS NULL clause; this will restrict the results returned to only those rows where the ID returned from Table2 is null - in other words there is NO record in Table2 for that particular ID from Table1. Table2.ID will be returned as NULL for all records from Table1 where the ID is not matched in Table2.
I would use EXISTS expression since it is more powerful, you can e.g. more precisely choose rows you would like to join. In the case of LEFT JOIN, you have to take everything that's in the joined table. Its efficiency is probably the same as in the case of LEFT JOIN with null constraint.
SELECT t1.ID
FROM Table1 t1
WHERE NOT EXISTS (SELECT t2.ID FROM Table2 t2 WHERE t1.ID = t2.ID)
SELECT id FROM table1 WHERE foreign_key_id_column NOT IN (SELECT id FROM table2)
Table 1 has a column that you want to add the foreign key constraint to, but the values in the foreign_key_id_column don't all match up with an id in table 2.
The initial select lists the ids from table1. These will be the rows we want to delete.
The NOT IN clause in the where statement limits the query to only rows where the value in the foreign_key_id_column is not in the list of table 2 ids.
The SELECT statement in parenthesis will get a list of all the ids that are in table 2.
Let we have the following 2 tables(salary and employee)
Now i want those records from employee table which are not in salary.
We can do this in 3 ways:
Using inner Join
select * from employee
where id not in(select e.id from employee e inner join salary s on e.id=s.id)
Using Left outer join
select * from employee e
left outer join salary s on e.id=s.id where s.id is null
Using Full Join
select * from employee e
full outer join salary s on e.id=s.id where e.id not in(select id from salary)
Where T2 is the table to which you're adding the constraint:
SELECT *
FROM T2
WHERE constrained_field NOT
IN (
SELECT DISTINCT t.constrained_field
FROM T2
INNER JOIN T1 t
USING ( constrained_field )
)
And delete the results.
From similar question here MySQL Inner Join Query To Get Records Not Present in Other Table I got this to work
SELECT * FROM bigtable
LEFT JOIN smalltable ON bigtable.id = smalltable.id
WHERE smalltable.id IS NULL
smalltable is where you have missing records, bigtable is where you have all the records. The query list all the records that not exist in smalltable but exists on the bigtable. You could replace id by any other matching criteria.
I Dont Knew Which one Is Optimized (compared to #AdaTheDev
) but This one seems to be quicker when I use (atleast for me)
SELECT id FROM table_1 EXCEPT SELECT DISTINCT (table1_id) table1_id FROM table_2
If You want to get any other specific attribute you can use:
SELECT COUNT(*) FROM table_1 where id in (SELECT id FROM table_1 EXCEPT SELECT DISTINCT (table1_id) table1_id FROM table_2);
You could opt for Views as shown below:
CREATE VIEW AuthorizedUserProjectView AS select t1.username as username, t1.email as useremail, p.id as projectid,
(select m.role from userproject m where m.projectid = p.id and m.userid = t1.id) as role
FROM authorizeduser as t1, project as p
and then work on the view for selecting or updating:
select * from AuthorizedUserProjectView where projectid = 49
which yields the result as shown in the picture below i.e. for non-matching column null has been filled in.
[Result of select on the view][1]
You can do something like this
SELECT IFNULL(`price`.`fPrice`,100) as fPrice,product.ProductId,ProductName
FROM `products` left join `price` ON
price.ProductId=product.ProductId AND (GeoFancingId=1 OR GeoFancingId
IS NULL) WHERE Status="Active" AND Delete="No"
SELECT * FROM First_table
MINUS
SELECT * FROM another
How to select rows with no matching entry in Both table?
select * from [dbo].[EmppDetails] e
right join [Employee].[Gender] d on e.Gid=d.Gid
where e.Gid is Null
union
select * from [dbo].[EmppDetails] e
left join [Employee].[Gender] d on e.Gid=d.Gid
where d.Gid is Null

select left join except one column

i have select:
SELECT t1.*, t2.* from t1 left join t2 on t2.id = t1.id
when id exist or not exist in t2 I want all columns from t2 except t2.id (which can be NULL).
Is there any way do this without print out all columns names in query?
thx
No, you have to either specify all columns of interest or use a wildcard.
SELECT *
FROM t1
LEFT JOIN t2
USING (id);
That is, by the way, the reason, why it is a good idea to name the columns that you are going to use in joins the same way across the database.
If the two tables have only id as a common column, you can also use this:
SELECT *
FROM t1
NATURAL LEFT JOIN
t2
Just switch the order of requested tables
instead
SELECT t1.*, t2.* from t1 left join t2 on t2.id = t1.id
use
SELECT t2.*, t1.* from t1 left join t2 on t2.id = t1.id
The Problem Occur With "ID" Now you can do like this:
"SELECT task.*, users.emp_id,users.emp_name,users.emp_designation from task
LEFT JOIN users ON task.userid=users.id where users.sup_id='1021' AND task.date='2022-09-03'"
here i will get the task table id and all data & users table 3 column . easy and simple

Simplifying this query?

Consider this query:
SELECT table1.id,
table1.review,
table1.time,
table2.author,
table2.title
FROM
table1, table2
WHERE table1.id = table2.id
AND table1.reviewer = '{$username}'
ORDER BY table1.id
I'm using the above quite a lot around my site's code. I find that adding the table prefixes etc. before the column names can make the query very long and take up quite a lot of lines.
Is there a way to make the above query simpler/easier?
First of all, you may want to give shorter aliases to your tables. In addition, you are using the implicit join syntax which complicates the WHERE clause, and is not recommended in general. You may want to use the more modern explicit syntax instead:
SELECT t1.id, t1.review, t1.time, t2.author, t2.title
FROM table1 AS t1
JOIN table2 AS t2 ON (t2.id = t1.id)
WHERE t1.reviewer = '{$username}'
ORDER BY t1.id
Note that JOIN is a synonym for INNER JOIN, and the AS keyword is optional when defining table aliases. You can simply use ... FROM table1 t1 ... instead of ... FROM table1 AS t1 ....
You can use table aliases
SELECT t1.id, t1.review, t1.time, t2.author, t2.title
FROM
table1 AS t1, table2 AS t2
WHERE t1.id = t2.id AND t1.reviewer = '{$username}'
ORDER BY t1.id
Why dont you make a function , pass the table name and other parameter and return either values or sql query.
Your query is already simplified, i think you are worried about doing this multiple times. so better will be to create a small function in that case.
I had similar problem, which i got rid using function.
You query looks pretty optimal aside from the potential risks with your "{$username}" portion. I could very easily see some SQL injection issues if the overall query is being rendered as a straight string and not via an abstract layer of some sort.
The format I find most readable is:
SELECT
t1.id,
t1.review,
t1.time,
t2.author,
t2.title
FROM
table1 t1
JOIN table2 t2
on ( t2.id = t1.id )
WHERE
t1.reviewer = '{$username}'
ORDER BY
t1.id
It's not clear if you're "using the above code all over the site" verbatim, or the style of SQL without aliases.
If this specific piece of code is being copy/pasted, consider encapsulating this logic in a function in your PHP modules.
function GetReviewerTitles($reviewer)
{
//your select statement.
$reviewerSQL = sprintf("SELECT t1.id, t1.review, t1.time, t2.author, t2.title FROM table1 as t1 INNER JOIN table2 AS t2 ON t1.id=t2.id WHERE t1.reviewer = '%s' ORDER BY t1.id",
mysql_real_escape_string({$username}));
// Perform Query
$result = mysql_query($reviewerSQL);
//return if/when necessary
}
I suggest using a view:
CREATE VIEW ReviewInfo(id, review, time, author, title, reviewer) AS
SELECT t1.id, t1.review, t1.time,
t2.author, t2.title, t1.reviewer
FROM table1 AS t1 JOIN table2 AS t2 ON t1.id = t2.id
Now you can write your query as:
SELECT id, review, time, author, title
FROM ReviewInfo
WHERE reviewer = '{$username}'
ORDER BY id;
Note the use of abbreviations for the table names in the view definition - that is a technique you could use in your query even if you don't use a view. And the notation using an explicit JOIN operator in the FROM clause with the ON condition is preferred to the old-style FROM table1, table2.

Categories