SQL - WHERE clause with JOIN - mysql

mysql_query("SELECT a.about,a.user,b.user,b.title,b.article,b.description
FROM about a
JOIN articles b ON b.user_id=a.user_id
WHERE MATCH(b.title,b.article) AGAINST ('$search')
");
I need to expand this query to include something like " AND user='$user'" but where both 'a' and 'b' tables are checked.
I could do "AND a.user='$user' AND b.user='$user'" but I will be adding 18 more tables so this is looking a bit bloated.
Is there any way to make things more compact?

You should only need to check the username on one table not both as the INNER JOIN using the user_id has already matched them up.
To be honest table b shouldn't really have a user field, instead it should just have the user_id field (this is considered normalised).
An INNER JOIN will then only return data where there is a match in both tables. So joining Table a.user_id to Table b.user_id ensures they both have a matching user_id.

Related

How to select every field from foreign table using intermediate table in SQL?

I have a question about pure SQL. I have a many to many relation with 3 tables: users, tags and user_tag. What I'm trying to do is select every field from the tags table, for as many entries where the user id matches the entries in user_tag.
The query I have right now looks like this
SELECT * FROM tags JOIN users_tags ON (users_tags.user_id = 1);
This retrieves the correct information (twice for some odd reason) but also appends unnecessary data from the pivot table (because of the SELECT *, but I need to keep it that way).
How can I only get relevant data from the tags table only then? (edited)
Thanks for your attention
You are missing the JOIN condition that connects the two tables. You only have a filtering condition. Something like this:
SELECT *
FROM tags t JOIN
users_tags ut
ON t.tag_id = ut.tag_id
WHERE ut.user_id = 1;
You haven't explained what the columns are, so of course the column names might be different.
The answer above works or i'm assuming if there's some name you want from the user table you could use this or a variation of this:
SELECT user.name, tags.*
FROM tags
INNER JOIN users_tags ON tags.tag_id = users_tags.tag_id
INNER JOIN user ON users_tags.user_id = users.user_id
where users_tags = 1;

MySQL Join statement to get data from two tables into a datagridview

I have two tables that I'm trying to join, 'holidays' and 'users'.
Users contains all my user info, the the column 'id' being primary and unique.
Holidays contains a column called 'userid', which corresponds to the id in the user table.
I'm struggling to get the join statement to work... what I'm looking for is the result of the select statement to give me the friendlyname (column 'fname' in user table) instead of giving me the value of userid.
Here's what I'm trying...
SELECT * FROM holidays JOIN users on users.id=holidays.userid WHERE holidays.status = 0
But i'm not getting a correct result - SQL executes without error, but my DGV is filled with tons of erroneous results.
Apologies If I have not used the correct terminology or whatever.
I'm new to the concept of joins.
Here is hopefully a better explanation of what I am after...
Thanks in advance.
You need to select the specific values you want from every table in the JOIN:
SELECT u.fname
FROM holidays h
JOIN users u
ON u.id = h.userid
WHERE h.status = 0
by the alias (FROM users u) you can select column from users table by u.fname
First try to right join to the User table. If you just want the fname then select the column name in the SELECT query, as SELECT * takes more time then SELECT column name.

How can I filter out results based on another table. (A reverse join I guess?)

Basically, I have a table which contains two fields: [id, other] which have user tokens stored in them. The goal of my query is to select a random user that has not been selected before. Once the user is selected it is stored in the table shown above. So if Jack selects Jim randomly, Jack cannot select Jim again, and on the flip side, Jim cannot select Jack.
Something like this is what comes to mind:
SELECT * FROM users
WHERE (SELECT * FROM selected WHERE (id=? AND other=?) OR (id=? AND other=?));
Well, first of all I've read that uses sub-queries like this is extremely inneficient, and I'm not even sure if I used the correct syntax, the problem is however, that I have numerous tables in my scenario which I need to filter by, so it would look more like this.
SELECT * FROM users u
WHERE (SELECT * FROM selected WHERE (id=? AND other=?) OR (id=? AND other=?))
AND (SELECT * FROM other_table WHERE (id=? AND other=?) OR (id=? AND other=?))
AND (SELECT * FROM diff_table WHERE (id=? AND value=?))
AND u.type = 'BASIC'
LIMIT = 1
I feel like there's a much, much more efficient way of handling this.
Please note: I don't want a row returned at all if the users id is present in any of the nested queries. Returning "null" is not sufficient. The reason I have the OR clause is because the user's id can be stored in either the id or the other field, so we need to check both.
I am using Postgre 9.5.3, but I added the MySQL tag as the code is mostly backwards comptable, Fancy Postgre only solutions are accepted(if any)
You can left join to another table, which produces nulls where no record is found:
Select u.* from users u
left selected s on s.id = u.id or s.other = u.other
where s.id is null
The or in a join is different, but should work. Example is kinda silly...but as long as you understand the logic. Left join first table to second table, where second table column is not null means there was atleast one record found that matched the join conditions. Where second table column is null means no record was found.
And you are right...avoid the where field = (select statement) logic when you can, poor performer there.
Use an outer join filtered on missed joins:
SELECT * FROM users u
LEFT JOIN selected s on u.id in (s.id, s.other) and ? in (s.id, s.other)
WHERE u.id != ?
AND s.id IN NULL
LIMIT 1

Doing a join on 3 tables

I have 3 sql tables
1) a table with headers of a coupon - id of this equals the id of the second table
2) a tables with details of the coupon - user_id on this tables equals user id of the third table
3) a table with details of user
So far I have this query
"SELECT kpn_processed_deals.kpn_id,
kpn_processed_deals.purchased_date, kpn_processed_deals.claim,
kpn_processed_deals.uid,kpn_deal_headers.kpn_type,
kpn_deal_headers.title,kpn_deal_headers.created_by
FROM kpn_processed_deals INNER JOIN kpn_deal_headers ON
kpn_processed_deals.kpn_id = kpn_deal_headers.kpn_id AND
kpn_deal_headers.created_by = '$var'";
This works just fine but I want to get the value of the users email on the third table using a join but I have been unsuccessful so far. Sorry if my formatting is messy. I'm horrible at these things.
Just add another JOIN.
"SELECT p.kpn_id, p.purchased_date, p.claim, p.uid,h.kpn_type, h.title, h.created_by, u.email
FROM kpn_processed_deals AS p INNER
JOIN kpn_deal_headers AS h ON p.kpn_id = h.kpn_id
JOIN kpn_deal_users AS u ON u.user_id = p.user_id
WHERE h.created_by = '$var'";
Also notice the use of table aliases, so you don't have to repeat the verbose table names throughout the query.
And constraints on single tables should normally be in the WHERE clause; the ON clause is for conditions related to joining the tables (an exception is in outer joins, where constraints on the child table need to be in the ON clause as well).

Need Help writing a MySQL query

I have a database with customer information, orders, etc. I need to run a query that returns all customers who have not placed an order at all.
Relevant tables: login and orders
Relevant Columns: login.loginID, login.loginFirstName, login.loginLastName, login.loginEmailAddress AND orders.OrderuserID
So essentially - in psuedocode: compare table login, column loginID for matches in the orders table under orders.OrderUserID. If no match exists (as in no orders placed) then output the users First Name, Last Name and Email address.
I have been racking my brain but having some real issues with the language. I'm a big time N00B when it comes to SQL.
Basically it'll look like that:
SELECT l.login_id
FROM login l
LEFT JOIN orders o
ON l.login_id = o.login_id
WHERE o.login_id IS NULL
The key is using LEFT JOIN with WHERE ... IS NULL condition. In other words, you specifically look for the rows in login table that don't have any information 'extended' within orders table.
That's just a general description, but I hope it should be helpful in your process of constructing the big query specific to your case. )
select loginFirstName, loginLastName, loginEmailAddress
from login
where loginID not in
(select distinct OrderuserID from orders)
You can also do it with a left join:
select loginFirstName, loginLastName, loginEmailAddress
from login left join orders on loginID = OrderuserID
where OrderuserID is null
Not sure which will execute faster; give it a try. The first is easier to understand, IMHO.
EDIT: "select distinct" means "return me the set of unique values of the field". So, the subquery in the first SQL returns the set of users (their IDs) who do have orders. If a user has multiple orders, DISTINCT makes sure her ID is returned only once.
This should do it:
select *
from login l
left join orders o on l.loginId = o.OrderuserID
where o.OrderuserID is null
Try:
select login.loginFirstName, login.loginLastName, login.loginEmailAddress
FROM login
LEFT OUTER JOIN orders ON login.loginID = orders.OrderuserID
WHERE orders.OrderuserID IS NULL;
or something like that. I suspect the trick for a newer SQL user is the LEFT OUTER join. Without that specifier, a join will only return rows from the first table IF there are matches in the second. This way you get them all (and then filter out matches with the IS NULL phrase).
Though you should try first yourself and you could search on google first :):) .
Anyways you can use it in this way,
SELECT l.loginFirstName,l.loginLastName,
l.loginEmailAddress FROM login AS l LEFT JOIN orders as o
ON l.loginID = o.OrderuserID where OrderuserID is NULL