I am sorry this is not a high quality question and I know I am risking downvotes, but I am trying to learn as I go. I am currently working on a side project and stumbled into a situation I am not sure of.
I have two tables and need to call the data from both sharing the same id number (different names)
I will now attempt to give an example
Table 1
| psid | idd |
| 1 | 999 |
| 2 | 42 |
Table 2
| aid | other |
| 999 | hello world |
| 42 | welcome |
I am trying to link idd and aid whilst displaying all rows from table one
Example
id = 1 / Title : hello world
id = 2 / Title : welcome
I am not sure if this can be achieved with a single query to the database I have tried adding a second but it goes in a nonstop loop.
I have not done much searching as not sure what to search for.
Thanks and sorry
Cartesian Join
SQLFiddle
select
table1.*,
table2.*
from
table1,
table2
where
table1.idd = table2.aid and
table1.idd = :id
Or Left Join
SQL Fiddle
select
t1.*,
t2.*
from
table1 t1
left join
table2 t2
on
t1.idd = t2.aid
where
t1.idd = :id
SELECT table1.psid, table2.other FROM table1
JOIN table2 ON table1.idd = table2.aid
WHERE table1.idd= 'X' AND table2.aid = 'X'
this should JOIN the two tables together and by specifying the matching id's for each table in the WHERE clause should get the relevant information.
EDIT fixed SQL
Related
I have two tables in my database where the first one has related values of the second one. Just like this:
table "people"
ID | NAME | SCHOOL
-------------------------
1 | john | 2
2 | fred | 1
3 | maria | 3
table "school"
ID | NAME
-------------------------
1 | first school
2 | second school
3 | third school
Ok.
I'm trying to make a select in "people" table and get the "SCHOOL" number replaced by "school" table related id.
So I did this:
"SELECT * FROM people A LEFT JOIN school B ON A.school = B.id"
That's ok!
But If I have to get the "people" ID value in this return, it will be replaced by "school" table ID value.
How can I solve this?
Thanks a lot!
If you are learning SQL, learn to list all the columns you want. Explicitly:
SELECT p.id, p.name, s.name as school_name
FROM
people p LEFT JOIN
school s
ON p.school = s.id;
Notes:
The table aliases are abbreviations for the table names. This makes the query much easier to follow.
A LEFT JOIN is not really needed here, but you are using it.
s.name could be aliased (s.name as school_name) to distinguish it from the person's name.
I have a junction table with Users ids and projects ids :
Every user can be on multiple projects.
id|UserID |ProjectID|
1 | 1| 2 |
2 | 2| 3 |
3 | 1| 3 |
4 | 3| 4 |
5 | 3| 2 |
6 | 3| 3 |
7 | 4| 5 |
Is it possible to return, with a single sql request all the id of user who are in the same projects as me ?
For example here, return me :
user 3, because he is in the projects 2 and 3 with me
user 2, because he is in the project 3 with me
I tried tu use DISTINCT with LEFT JOIN, but i can't find how to use it with only one table...
Thanks
There are usually a few ways you can achieve something like this in sql. The first method is one that I would have written, just to show you an alternate way of thinking about it. I also wrote a left join as you were attempting to show you that method as well.
Method #1
SELECT DISTINCT UserID
FROM Table
WHERE ProjectID IN (SELECT DISTINCT ProjectID FROM Table WHERE UserID = me)
Method #2
SELECT DISTINCT others.UserID
FROM Table myself
LEFT JOIN Table others ON myself.ProjectID = others.ProjectID
WHERE myself.UserID = me
cant think of anything better for now
declare #searchingId int;
set #searchingId = 1
select distinct t2.UserId
from
(select t1.ProjectId
from [Table] as t1
where t1.UserId = #searchingId) as projects
join [Table] as t2 on projects.ProjectId = t2.ProjectId
where t2.UserId != #searchingId
I would use a simple join:
select distinct upr.userid
from userprojects upr join
userprojects upr2
on upr2.projectid = upr.projectid and
upr2.userid = #me;
If you want to, say, count the number of matching projects, use group by:
select upr.userid, count(*)
from userprojects upr join
userprojects upr2
on upr.projectid = upr.projectid and
upr2.userid = #me
group by upr.userid;
Suppose i have three table. first table got wine_name and wine_id, 2nd table got wine_id,varie_id and the 3rd table got variety_id and variety_name. I just want to show the wine name with the variety name. I tried inner join but cdnt get the result, jst getting error. can some suggest me what should i write.
Are you looking for this?
SELECT w.wine_name, v.variety_name
FROM wine_variety wv JOIN wines w
ON wv.wine_id = w.wine_id JOIN varieties v
ON wv.variety_id = v.variety_id
Sample output:
| WINE_NAME | VARIETY_NAME |
----------------------------
| Wine 1 | Variety 1 |
| Wine 2 | Variety 2 |
Here is SQLFiddle demo
Try below code
select table1.wine_name, table3.variety_name from table1 inner join
table2 on table1.wine_id = table2.wineid left
join table3 on table2.varieId = table3.varietyID
Hope you can help me with correct syntax of a SQL query (using MySQL 5.5.25).
I have 3 tables:
data
data_tmp
users
data table is empty - has it's own structure but no rows
data:
id | name | who
----------------
data_tmp:
id | cars | who
---------------
1 | lambo| 2
users
who | name |
------------
2 | john
My query is:
SELECT DISTINCT
users.name,
(SELECT count(id) FROM data WHERE who = 1) as number,
data_tmp.cars
FROM
users, data, data_tmp
WHERE
users.who = 2
AND data_tmp.who = 2
AND data.who = 2
This of course returns an empty result (there is no row that suits to all parameters because data is empty).
What I would like to achieve is:
users.name | number | data_tmp.cars |
-------------------------------------
john | 0 | lambo |
I am sure I have to - in some way - use LEFT JOIN but can't find correct syntax. Hope you can help me.
Kalreg
give this a try (without using subquery)
SELECT a.name, b.cars, count(c.id) as number
FROM users a
INNER JOIN data_tmp b
on a.who = b.who
LEFT JOIN data c
on a.who = c.who AND
a.name = c.name
WHERE a.who = 2
GROUP BY a.name, b.cars
this works on different servers:
MSSQL SERVER # SQLFIDDLE
MYSQL # SQLFIDDLE
Your assumption is right: you have to use left JOIN, in this way :
SELECT DISTINCT users.name, (SELECT count(id) FROM data WHERE who = 1) as number, data_tmp.cars
FROM users
JOIN data_tmp USING (who)
LEFT JOIN data USING(who)
WHERE users.who = 2
I've been looking all over the net and asking people for guidance but nobody seems to know the right (relatively fast) solution to the problem:
I have three tables, classic many-to-many solution:
entries: id (int), title (varchar[255]), content (text)
tags: id (int), name (varchar[255]), slug (varchar[255])
entries_tags: id (int), entry_id (int), tag_id (int)
Nothing out of ordinary so far. Now let's say I have test data in tags (I'm keeping out slugs as they are not important):
ID | name
1. | one
2. | two
3. | three
4. | four
5. | five
I also have three entries:
ID | title
1. | Something
2. | Blah blah blah
3. | Yay!
And relations:
ID | entry_id | tag_id
1. | 1 | 1
2. | 1 | 2
3. | 2 | 1
4. | 2 | 3
5. | 3 | 1
6. | 3 | 2
7. | 3 | 3
8. | 4 | 1
9. | 4 | 4
OK, we have our test data. I want to know how to get all entries that have tag One, but doesn't have tag Three (that'd be entries 1 and 4).
I know how to do it with subquery, the problem is, it takes a lot of time (with 100k entries it took about 10-15 seconds). Is there any way to do it with JOINs? Or am I missing something?
edit I guess I should've mentioned I need a solution that works with sets of data rather than single tags, so replace 'One' in my question with 'One', 'Two' and 'Two' with 'Three','Four'
edit2 The answer provided is right, but it's too slow to be used practically. I guess the only way of making it work is using a 3rd-party search engine like Lucene or ElasticSearch.
The following script selects entries that have tags One and Two and do not have tags Three and Four:
SELECT DISTINCT
et.entry_id
FROM entries_tags et
INNER JOIN tags t1 ON et.tag_id = t1.id AND t1.name IN ('One', 'Two')
LEFT JOIN tags t2 ON et.tag_id = t2.id AND t2.name IN ('Three', 'Four')
WHERE t2.id IS NULL
Alternative solution: the INNER JOIN is replaced with WHERE EXISTS, which allows us to get rid from the (rather expensive) DISTINCT:
SELECT
et.entry_id
FROM entries_tags et
LEFT JOIN tags t2 ON et.tag_id = t2.id AND t2.name IN ('Three', 'Four')
WHERE t2.id IS NULL
AND EXISTS (
SELECT *
FROM tags t1
WHERE t1.id = et.tag_id
AND t1.name IN ('One', 'Two')
)
This should do what you want.
(It may or may not be faster than the sub query solution, I suggest you compare the query plans)
SELECT DISTINCT e.*
FROM tags t1
INNER JOIN entries_tags et1 ON t1.id=et1.tag_id
INNER JOIN entries e ON e.entry_id=et1.entry_id
INNER JOIN tags t2 on t2.name='three'
INNER JOIN tags t3 on t3.name='four'
LEFT JOIN entries_tags et2 ON (et1.entryid=et2.entryid AND t2.id = et2.tag_id )
OR (et1.entryid=et2.entryid AND t3.id = et2.tag_id )
WHERE t1.name IN ('one','two') AND et2.name is NULL
By LEFT Joining the entries_tags table et2 (the data you do not want), you can then only select the records where the et2.name IS NULL (where the et2 record does not exist).
You mentioned trying a subquery. Is this what you tried?
SELECT entries.id, entries.content
FROM entries
LEFT JOIN entries_tags ON entries.id=entries_tags.entries_id
LEFT JOIN tags ON entries_tags.tag_id=tags.id
WHERE tag.id=XX
and entries.id NOT IN (
SELECT entries.id
FROM entries
LEFT JOIN entries_tags ON entries.id=entries_tags.entries_id
LEFT JOIN tags ON entries_tags.tag_id=tags.id
WHERE tag.id=YY
)
(Where XX is the tag you do want and YY is the tag you do not want)
With indices on the ID fields, that shouldn't be as slow as you say it is. It will depend on the data set, but it should be fine with indices (and with string comparisons omitted).