So I've been looking through how to get this to work and haven't been able to find it, or really even properly search.
I'm looking to join t1 to t2 where I get ALL results from t1, and it's only joined where t2's column value is "something", the table is set up that there are many items in the t2 column. So if t2's column doesn't equal "something", then just have the other data (but mainly I only want ONE of each value for t1 row, because there will be a max of one t2 row that qualifies per t1 row).
select * t1 LEFT JOIN t2 where t2.column="something" AND t1 conditions.
Any help would be appreciated, the tables are WordPress tables, and the thing I'm asked to do would be easier done without WordPress knowing.
--
Actual code attempt:
$ SELECT * FROM posts LEFT JOIN postmeta ON post_id = id WHERE post_status='publish' AND post_type='portfolio' AND meta_key='rjmeta_video'
$Table 1
$ID Title ....
$----------------------
$5 Some post I need outside of WP
$Table 2
$meta_id post_id meta_key ....
$--------------------------------
$3 5 rjmeta_video
$4 5 _edit_lock
$5 5 _edit_last
I believe this is what you mean:
select distinct t1.* from t1
LEFT JOIN t2 on [condition for join] and t2.column="something"
where [t1 conditions].
This assumes that you are only interested in the t1 fields.
What we don't know:
table schemas
how are they joined? t2.t1_id = t1.id ?
t1 conditions
DISTINCT used above will eliminate duplicate rows if there are multiple matches for the join
EDIT (OP comment response):
SELECT distinct posts.* FROM posts
LEFT JOIN postmeta ON (post_id = id and meta_key='rjmeta_video')
WHERE post_status='publish' AND post_type='portfolio'
This assumes that 'rjmeta_video' is the "something" you were referring to originally
Related
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
This has been asked and answered in different instances but all that I've seen doesn't quite work for my problem.
PROBLEM: I have 3 tables I need to pull data from at the same time to compare and retrieve information from. All 3 tables contain an 'email' column. Now, a user's email from table1 may match same user's email in both table2 AND table3, depending on user's status. OR an email from table1 will ONLY match either an email in table2 or table3, depending on user's status again. For example, a user may have a red status (user will show in table2), a blue status (user will show in table3), or both, red and blue (user will show in both, table2 and table3).
WHAT IS NEEDED: an email from table1 needs to be compared to email in table2 and table3 and return a region value for a given user, which is recorded in table2 and table3 but not in table1. I know. Delightful data architecture! Either way, I was able to JOIN table1 to table2 very successfully but I am not sure how to slap on a JOIN with table3.
Here's the query for 2 tables:
SELECT * FROM table1
INNER JOIN table2
ON table2.email = table1.email
WHERE month = 'numberHere' ORDER BY submitdate DESC
When I simply add another INNER JOIN my code doesn't break per say but it doesn't give me any rows to be displayed either. So the code below doesn't work despite the many working examples from the web:
SELECT * FROM table1
INNER JOIN table2
ON table2.email = table1.email
INNER JOIN table3
ON table3.email = table2.email
WHERE month = 'numberHere' ORDER BY submitdate DESC
To match the row from table1 in any case and the rows of other tables only if they are, you have to use LEFT JOIN, joining table2 and table3 with table1 (not table2 with table1 and table3 with tabel2):
SELECT * FROM table1
LEFT JOIN table2
ON table2.email = table1.email
LEFT JOIN table3
ON table3.email = table1.email
In this way you select values from table1 even without a match in other tables.
See more about SQL Joins: Different SQL Joins
You need to use LEFT JOIN, so that the joins will succeed even if there's no matching row in one of the tables.
SELECT * FROM table1
LEFT JOIN table2
ON table2.email = table1.email
LEFT JOIN table3
ON table3.email = table2.email
WHERE month = 'numberHere'
AND (table2.email IS NOT NULL OR table3.email IS NOT NULL)
ORDER BY submitdate DESC
The additional conditions filter out rows that have no match in either of the tables.
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
i have the following query that pulls posts that belong to a blog
SELECT p.*
FROM `Posts` p
INNER JOIN Blogs b ON b.id = p.blog_id
Is there a MySQL function that does the opposite of "ON"? If i wanted to query posts that didn't belong to a blog in the "Blogs" database table? For instance if the blog was deleted.
You need to use either LEFT JOIN - NULL combo, like this:
SELECT p.*
FROM Posts p
LEFT OUTER JOIN Blogs b
ON b.id = p.blog_id
WHERE b.id IS NULL
... or NOT IN dependent query (with so-called 'anti-join'):
SELECT *
FROM Posts
WHERE blog_id NOT IN (SELECT id FROM Blogs)
I admit I almost exclusively use the first form, but actually they have the similar performance: I'd recommend at least glancing through this article with detailed explanation of similarities and differences between these queries; it's quite an enlightening reading. )
It's all about the JOIN.
SELECT p.*
FROM `Posts` p
LEFT OUTER JOIN Blogs b ON b.id = p.blog_id
WHERE b.Id IS NULL
Should do the trick for you.
Jeff Atwood has a great overview of joins
In this instance, what the LEFT OUTER JOIN does is match all rows in Blogs with all rows in Posts with the same blog_id-Id combo AND all rows in Posts that have no matching Id in Blogs. In this instance, those rows are NULL for the entries in Blogs (as there aren't any!), which is why we filter on b.Id IS NULL
There are some other ways you can achieve this too; for example:
SELECT * FROM Posts WHERE blog_id NOT IN (SELECT Id FROM Blogs)
Effectively, this queries all rows in posts that have a blog_id that isn't in the blog table.
Running an EXPLAIN on some of my query tests have resulted in slow ALL joins even with indexes.
How do I make a MYSQL query with the following information more efficient?
Tables
counter: id (pk), timestamp, user_id (fk)
user: id (PK), username, website_id (fk)
website: id (pk), sitename
SELECT t2.username, t3.sitename, count(*) as views FROM counter t1
LEFT JOIN user t2 ON t2.id = t1.user_id
LEFT JOIN website t3 ON t3.id = t2.website_id
WHERE t1.id <> ""
GROUP BY t1.id
ORDER BY t1.id DESC
The result in an html table:
username, sitename, counter_views
Don't count(*), instead use count(t1.id)
Question Edit Change
With the question edit, you should put a column name in the count statement of what you want to count, e.g. count(user.id)
I believe the sql is wrong. Don't you want this:
select u.username, s.sitename, count(c.id)
from user u
join website s on u.website_id = s.id
join counter c on u.id = c.user_id
where u.id <> ""
group by u.username, s.sitename
order by u.id desc
Is your data populated yet? If these tables are empty, or very small, the optimizer may be choosing an 'all' query because the whole table is on one page. One page load from disk to get the whole table is faster than hitting a page on disk for the index, and then another page for the real data page.
Your query looks wrong. I would use something like this:
SELECT u.username, w.sitename, c.views
FROM (
SELECT user_id, COUNT(*) AS views FROM counter GROUP BY user_id
) AS c
LEFT JOIN user u ON u.id = c.user_id
LEFT JOIN website w ON w.id = u.website_id
ORDER BY c.views DESC
I would add index for counter.user_id too.