On the page I have an one query, which is bring page loading speed down.
SELECT * FROM users1 WHERE user_id NOT IN (SELECT user_id FROM users2)
USERS1 is the table with all users of the site, a lot of data.
USERS2 is the table of following eachother users.
So, I need to select some users, which is not alredy following.
Any ways of optimisation?
I'm posting real query:
SELECT users.*
FROM (
SELECT user_id
FROM users
WHERE user_id!=156 AND user_id NOT IN (
SELECT follower_id
FROM following
WHERE user_id=156
) ORDER BY RAND() LIMIT 2
) AS temp
JOIN users ON users.user_id = temp.user_id;
Indexes on user_id fields.
Query took 0.0912 sec
This query works not bad on the testing server with less data, but it takes up to 3 seconds on live one.
LEFT JOIN way:
SELECT *
FROM users1
LEFT JOIN users2 ON users1.user_id = users2.user_id
WHERE users2.user_id IS NULL
NOT EXISTS way:
SELECT *
FROM users1
WHERE NOT EXISTS (SELECT 1 FROM users2 WHERE users1.user_id = users2.user_id)
Working examples: http://sqlfiddle.com/#!2/611f2/1
You should use LEFT JOIN for best performance as:
SELECT a.*
FROM users1 a
LEFT JOIN users2 b
ON a.user_id = b.user_id
WHERE b.user_id IS NULL;
Also have a look at Visual explanation of joins
This should do the trick:
SELECT users1.* FROM users1
LEFT JOIN users2 on users1.user_id=users2.user_id
WHERE users2.user_id IS NULL
Related
I have an application that has a referral system where users can use their user_id to refer another user. All users are on the same table. The referrals table stores the user_id for the referrer and for the referred.
Users Table:
Referrals Table:
I want to query the names of both users (referrer and referred) from the user's table using their user_id that is populated in the referrals table.
Expected Result:
select t2.name as referrer_name,t3.name as referred_name
from REFERRALS_TABLE t1
left join USER_TABLE t2 ON t1.referrer=t2.user_id
left join USER_TABLE t3 ON t1.referred=t3.user_id
I method is to join the User_table twice -
SELECT U1.name referrers_name, U2.name referred_name
FROM Referrals R
JOIN Users U1 ON R.referrer = U1.user_id
JOIN Users U2 ON R.referrd = U1.user_id
You use sql UNION if get two table data and multiple where clouse.
SELECT * FROM oauth_clients WHERE user_id=2
UNION
SELECT * FROM photos where gallery_id=12
I am trying to find all of the users which do not have any orders.
So far I've tried the following:
select * from `users` where not exists
(select * from `orders` where `users`.`id` = `orders`.`user_id`)
I've also tried the following:
select users.*, count(distinct orders.reference) as orders_count from `users`
left join `orders` on `users`.`id` = `orders`.`user_id`
group by `users`.`id` having orders_count = 0
However, both are very slow running queries. There are around 5000 customers and 30,000+ orders. Is there a more efficient way of doing this?
You need to limit your subquery to only look at user_id. Also make sure user_id is indexed.
Alter table orders add index(user_id)
Select * from users where id NOT IN(select user_id from
orders)
I have three tables -
Users [Id,Name]
Matches_A [Id1,Id2]
Matches_B[Id1,Id2]
I know the user_id of the current user.
For each Id1, in either matches table, there are many entries. That is there are many matches for each user in both tables.
I need to select all of the users who are not in either matches table.
I tried this query -
SELECT * FROM Users
JOIN Matches_A ON Users.id = Matches_A.id2
JOIN Matches_B on Users.id = Matches_B.id2
WHERE Matches_A.id1 != $userid
AND Matches_B.id1 != $userid;
This doesn't work.
The problem is that there are entries in the Matches table with the same id2 but different id1s. That means that even if I exclude a row where the id1 matches the userid, that user (id2) could still be returned because there is another row with the same user where the id1 does not match the user_id.
If that made no sense, let me rephrase it. It would be easy to select everything that I don't want to be returned.
SELECT * FROM Users
JOIN Matches_A ON Users.id = Matches_A.id2
JOIN Matches_B on Users.id = Matches_B.id2
WHERE Matches_A.id1 != $userid
AND Matches_B.id1 = $userid;
Would return all of the rows that I don't want. How can I write a query that will get me all the other rows.
P.S. It's pretty easy to do this with a sub-query, but I'm worried that will be slow especially with 3 tables.
Think not in or not exists instead of join:
SELECT *
FROM Users u
WHERE u.id NOT IN (SELECT a.id2 FROM Matches_A) AND
u.id NOT IN (SELECT b.id2 FROM Matches_B);
This version assumes that id2 is never NULL in either table.
You can try with NOT EXISTS also
SELECT u.*
FROM Users u
WHERE NOT EXISTS (SELECT a.id2 FROM Matches_A a WHERE a.id2 = u.id
UNION ALL
SELECT b.id2 FROM Matches_B b WHERE b.id2 = u.id)
The simplest solution is to use EXCEPT
WITH Subset as (SELECT id from users EXCEPT
(SELECT id2 from Matches_A
UNION
SELECT id2 from Matches_B))
SELECT * FROM Users NATURAL JOIN Subset;
I have multiple tables as table_1 has id , p_code, profile_status, name and table_2 has id, p_code, availablity and table_3 has id, p_code, status...
How to get all records form all tables depend on p_code.
table_2 and table_3 has few records. if p_code not in table_2 and table_3 then echo 'no' in results.
currently i am using my query as below
select t.id, t.p_code,t.name,t.num_rooms, t.profile_status, t.distance FROM (
( SELECT id , p_code, profile_status, name,num_rooms, 3956 * 2 * ASIN(SQRT( POWER(SIN(($origLatAirport - latitude)*pi()/180/2),2)
+COS($origLatAirport*pi()/180 )*COS(latitude*pi()/180)
*POWER(SIN(($origLonAirport-longitude)*pi()/180/2),2)))
as distance FROM property WHERE profile_status=1 having distance < ".$dist." ) ) as t
How to add table_2 and table_3 and fetch results.
Pleasr reply soon. I am stuck here.
In your query you are doing CROSS JOIN and what you desire, is probably INNER JOIN.
In MySQL the CROSS JOIN behaves like JOIN and INNER JOIN of without using any condition.
The CROSS JOIN returns all rows form user multiplied by all rows from user_inbox - for every user you get inboxes of all users.
You should specify condition for your JOIN statement.
$sql_alt = mysql_query(
"select i.*,u.images, u.firstname, u.lastname
from user_inbox i INNER JOIN user u ON i.to_id = u.user_id
where i.to_id = '$user_id'");
Also it is good habit have the same names for primary and foreign keys, so I think you should have user_id or user_id_to instead of to_id in your user_inbox table. This is of course not absolutely necessary.
I need to get the users age by his ID. Easy.
The problem is, at the first time I don't know their IDs, the only thing I know is that it is in a specific table, let's name it "second".
SELECT `age` FROM `users` WHERE `userid`=(SELECT `id` FROM `second`)
How can I do that?
SELECT age FROM users WHERE userid IN (SELECT id FROM second)
This should work
Your example
SELECT `age` FROM `users` WHERE `userid`=
(SELECT `id` FROM `second`
WHERE `second`.`name` = 'Berna')
should have worked as long as you add a where criteria. This is called subqueries, and is supported in MySQL 5. Reference http://dev.mysql.com/doc/refman/5.1/en/comparisons-using-subqueries.html
SELECT
age
FROM
users
inner join
Second
on
users.UserID = second.ID
An inner join will be more efficient than a sub-select
SELECT age FROM users WHERE userid IN (SELECT id FROM second)
but preferably
SELECT u.age FROM users u INNER JOIN second s ON u.userid = s.id
You want to use the 'in' statement:
select * from a
where x=8 and y=1 and z in (
select z from b where x=8 and active > '2010-01-07 00:00:00' group by z
)