I'm a complete SQL noob and have no idea how to utilize JOINs. If someone could help with this query, it would be great.
I have a table questions which contains two columns: queid and que.
Another table options, contains the corresponding options for the questions, and has columns optionid, queid,option.
How can I do a SELECT statement such that I can join both tables together based on queid ?
Something like:
SELECT * from questions,options where queid=1
You should try this:
SELECT que.*, opt.* FROM questions que
INNER JOIN options opt ON que.queid = opt.queid
WHERE que.queid = 1
INNER JOIN loads questions and options having at least one corresponing record in every table.
If you need to get all questions (even the ones not having options) you could use
SELECT que.*, opt.* FROM questions que
LEFT JOIN options opt ON que.queid = opt.queid
WHERE que.queid = 1
LEFT JOIN always loads questions and, if they have options, their options too; if not you get NULL for options columns.
May be by
SELECT * FROM questions q JOIN options o ON q.queid=o.queid WHERE q.queid=1
SELECT q.*,o.* FROM questions q
JOIN options o ON q.queid = o.queid
WHERE q.queid = 1
SELECT *
FROM questions
JOIN options ON questions.queid = options.queid
WHERE questions.queid = 1
You can join two related tables using the column that they have in common.
in your case you can write :
SELECT * FROM Questions as Q INNER JOIN Options O ON Q.queid=O.queid WHERE Q.quid=1
You can also omit the where part like this :
SELECT * FROM Questions as Q INNER JOIN Options O ON Q.queid=O.queid AND Q.quid=1
There are different kind of joins :
INNER
OUTER(Left,Right,Full)
By inner join you mean that only records that are common in both tables are returned
When you use outer join all the records on the given side are return plus the records that have corresponding values on the other side otherwise instead of the other side values you will get null.
Related
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;
I have two tables:
Users <----> Questions
They use a ManyToMany relation table to keep track of which user answered which question.
Users <----> UsersQuestions <----> Questions
Now I need to write a query which fetches all the questions a specific user id has NOT answered yet.
The following native query works fine:
SELECT * FROM questions q
WHERE q.id NOT IN (
SELECT question_id FROM users_questions
WHERE user_id = 4
);
But I directly access the UsersQuestions table in this query and I haven't found a way to do so in Doctrine yet, I don't even think it's possible.
The only way to access that table is by joining on a property of my Question class, thus I tried to rewrite the query to the following one which also works fine as a native query:
SELECT * questions q
LEFT JOIN users_questions uq
ON q.id = uq.question_id AND uq.user_id = 4
WHERE uq.user_id IS NULL;
I was assuming that I could simply rewrite this into DQL as the following query:
SELECT q FROM MyBundle:Question q
LEFT JOIN q.usersAnswered uq WITH uq.id = 4
WHERE uq.id IS NULL
When I call $query->getSql() I get the following output:
SELECT * FROM mybundle_questions g0_
LEFT JOIN users_questions u2_
ON g0_.id = u2_.question_id
LEFT JOIN mybundle_users g1_
ON g1_.id = u2_.user_id AND (g1_.id = 4)
WHERE g1_.id IS NULL
Which to me looks fine given my very basic knowledge on Doctrine and queries in general. However, this fetches and returns ALL the questions which are in the table and not only the ones which this users hasn't answered yet.
Did I make a mistake somewhere? Or is there any other/easier way to fetch these unanswered questions? I feel like I'm reinventing the wheel here.
Been stuck on this for days and every attempt that I make in native SQL works fine, but I can't translate it to DQL. Any help would be appreciated.
I've solved my problem with the following query. Looks like it WAS possible to create a subquery after all.
SELECT q FROM MyBundle:Question q
WHERE q.id NOT IN (
SELECT uq.id FROM MyBundle:User u
INNER JOIN u.questionsAnswered uq
WHERE u.id = 4
)
Which Doctrine translates to the following query:
SELECT * FROM myBundle_questions g0_
WHERE g0_.id NOT IN (
SELECT g1_.id FROM myBundle_users g2_
INNER JOIN users_questions u3_
ON g2_.id = u3_.user_id
INNER JOIN myBundle_questions g1_
ON g1_.id = u3_.question_id
WHERE g2_.id = ?
)
For some reason the previous query, although it looked good in my eyes, didn't work. Must have something to do with how Doctrine handles the left join / null situations. However, this query in which I approach the problem from a different angle work perfectly.
I'm using 3 tables to collect data from. The proces looks like:
User write VIN to form
Script search in table 1 for case_id and country base on that vin
number
After that he use case_id and country for search in table number 2
and get calculation id from there
Base on that calculation id and case id it search in 3th table
.
My script looks like this:
SELECT
cases.case_id,
cases.lastcalc_model_options,
cases.country,
calculations.calculation_id,
calculations.license,
positions.text
FROM cases
INNER JOIN calculations ON(cases.case_id =calculations.case_id
AND cases.country = calculations.country)
INNER JOIN positions ON(calculations.case_id = positions.case_id
AND calculations.calculation_id = positions.calculation_id)
WHERE vin ='ABCDEFGH'
This select work correctly, problem start when for example there is for example no result in table positions with that case_id and calculation_id. Instead of give back atleast everything it found in other tables it return NOTHING.
Is there a way to change this kind of komplex SELECT to return everything it found not return something only when every condition is TRUE?
Your problem is the INNER JOIN. Using INNER JOIN your result only contains entries present in all tables. Try using LEFT JOIN instead.
SELECT
cases.case_id,
cases.lastcalc_model_options,
cases.country,
calculations.calculation_id,
calculations.license,
positions.text
FROM cases
LEFT JOIN calculations ON(cases.case_id =calculations.case_id
AND cases.country = calculations.country)
LEFT JOIN positions ON(calculations.case_id = positions.case_id
AND calculations.calculation_id = positions.calculation_id)
WHERE vin ='ABCDEFGH'
See this stackoverlow answer for some more indepth information.
INNER JOIN returns rows from both tables only if there is a match between the columns in both tables.
You may try LEFT JOIN or FULL OUTER JOIN instead.
I have database with schema on picture below and I need to select everything related to one row (one id) of [letaky]. That means the related [zamestnanci], every related [obsah] and every [knihy] in it.
This is the first time i used relations in database and i have no idea how to make such a select.
Use JOIN ... ON:
SELECT *
FROM zamestnanci
JOIN lekaty ON lekaty.zamestnanciid = zamestnanci.id
JOIN obsah ON obsah.idletaku = lekaty.id
JOIN knihy ON knihy.id = obsah.idknihy
WHERE letaky.id = 123
You may also want to consider whether you need INNER JOIN, LEFT JOIN or RIGHT JOIN for each of these joins. The difference between these JOINs is described in many other questions on StackOverflow, for example this one:
SQL Join Differences
I know the usage of joins, but sometimes I come across such a situation when I am not able to decide which join will be suitable, a left or right.
Here is the query where I am stuck.
SELECT count(ImageId) as [IndividualRemaining],
userMaster.empName AS ID#,
CONVERT(DATETIME, folderDetails.folderName, 101) AS FolderDate,
batchDetails.batchName AS Batch#,
Client=#ClientName,
TotalInloaded = IsNull(#TotalInloaded,0),
PendingUnassigned = #PendingUnassigned,
InloadedAssigned = IsNull(#TotalAssigned,0),
TotalProcessed = #TotalProcessed,
Remaining = #Remaining
FROM
batchDetails
Left JOIN folderDetails ON batchDetails.folderId = folderDetails.folderId
Left JOIN imageDetails ON batchDetails.batchId = imageDetails.batchId
Left JOIN userMaster ON imageDetails.assignedToUser = userMaster.userId
WHERE folderDetails.ClientId =#ClientID and verifyflag='n'
and folderDetails.FolderName IN (SELECT convert(VARCHAR,Value) FROM dbo.Split(#Output,','))
and userMaster.empName <> 'unused'
GROUP BY userMaster.empName, folderDetails.folderName, batchDetails.batchName
Order BY folderDetails.Foldername asc
Yes, it depends on the situation you are in.
Why use SQL JOIN?
Answer: Use the SQL JOIN whenever multiple tables must be accessed through an SQL SELECT statement and no results should be returned if there is not a match between the JOINed tables.
Reading this original article on The Code Project will help you a lot: Visual Representation of SQL Joins.
Also check this post: SQL SERVER – Better Performance – LEFT JOIN or NOT IN?.
Find original one at: Difference between JOIN and OUTER JOIN in MySQL.
In two sets:
Use a full outer join when you want all the results from both sets.
Use an inner join when you want only the results that appear in both
sets.
Use a left outer join when you want all the results from set a, but
if set b has data relevant to some of set a's records, then you also
want to use that data in the same query too.
Please refer to the following image:
I think what you're looking for is to do a LEFT JOIN starting from the main-table to return all records from the main table regardless if they have valid data in the joined ones (as indicated by the top left 2 circles in the graphic)
JOIN's happen in succession, so if you have 4 tables to join, and you always want all the records from your main table, you need to continue LEFT JOIN throughout, for example:
SELECT * FROM main_table
LEFT JOIN sub_table ON main_table.ID = sub_table.main_table_ID
LEFT JOIN sub_sub_table on main_table.ID = sub_sub_table.main_table_ID
If you INNER JOIN the sub_sub_table, it will immediately shrink your result set down even if you did a LEFT JOIN on the sub_table.
Remember, when doing LEFT JOIN, you need to account for NULL values being returned. Because if no record can be joined with the main_table, a LEFT JOIN forces that field to appear regardless and will contain a NULL. INNER JOIN will obviously just "throw away" the row instead because there's no valid link between the two (no corresponding record based on the ID's you've joined)
However, you mention you have a where statement that filters out the rows you're looking for, so your question on the JOIN's are null & void because that is not your real problem. (This is if I understand your comments correctly)