Inner Join SQL Syntax - mysql

I've never done an inner join SQL statement before, so I don't even know if this is the right thing to use, but here's my situation.
Table 1 Columns: id, course_id, unit, lesson
Table 2 Columns: id, course_id
Ultimately, I want to count the number of id's in each unit in Table 1 that are also in Table 2.
So, even though it doesn't work, maybe something like....
$sql = "SELECT table1.unit, COUNT( id ) as count, table2.id, FROM table1, table2, WHERE course_id=$im_course_id GROUP BY unit";
I'm sure the syntax of what I'm wanting to do is a complete fail. Any ideas on fixing it?

SELECT unit, COUNT( t1.id ) as count
FROM table1 as t1 inner JOIN table2 as t2
ON t1.id = t2.id
GROUP BY unit
hope this helps.

If I understand what you want (maybe you could post an example input and output?):
SELECT unit, COUNT( id ) as count
FROM table1 as t1 JOIN table2 as t2
ON t1.id = t2.id
GROUP BY unit

Okay, so there are a few things going on here. First off, commas as joins are deprecated so they may not even be supported (depending on what you are using). You should probably switch to explicitly writing inner join
Now, whenever you have any sort of join, you also need on. You need to tell sql how it should match these two tables up. The on should come right after the join, like this:
Select *
From table1 inner join table2
on table1.id = table2.id
and table1.name = table2.name
You can join on as many things as you need by using and. This means that if the primary key of one table is several columns, you can easily create a one-to-one match between tables.
Lastly, you may be having issues because of other general syntax errors in your query. A comma is used to separate different pieces of information. So in your query,
SELECT table1.unit, COUNT( id ) as count, table2.id, FROM ...
The comma at the end of the select shouldn't be there. Instead this should read
SELECT table1.unit, COUNT( id ) as count, table2.id FROM ...
This is subtle, but the sql query cannot run with the extra comma.
Another issue is with the COUNT( id ) that you have. Sql doesn't know which id to count since table1 and table2 both have ids. So, you should use either count(table1.id) or count(table2.id)

Related

Specify table-column on "in" operator

i would like to know if there is any shortcut to specify the column where IN have to check for matches.
Example:
Instead of this:
select *
from table1
where id in(
select column
from table2
)
something like this:
select *
from table1
where id in table2.column
I know the existence of TABLE for IN, ANY, SOME to specify a table, but it works only if the table specified is composed by just 1 column
EDIT: using join is not an option, because the real use i was looking for is on a NOT IN operator, and also JOIN create duplicates sometimes like in a one to many relation
There is no shortcut like that in SQL. Let me explain why.
In a query, all table references need to be made in the FROM clause. Hence, you cannot simply refer to table2.col unless table2 has been defined in the FROM clause. table2 is actually an alias, which defaults to the table name.
From a performance perspective, I would recommend exists:
select t1.*
from table1 t1
where exists (select column
from table2 t2
where t2.column = t1.id
)
In particular, this can take advantage of an index on table2(column) and has the same semantics as in.
Using a JOIN is a bit shorter. At least it does not require a subquery or another SELECT ... FROM.
SELECT table1.*
FROM table1
JOIN table2 ON table1.id = table2.column
Although this simple example is an inner join, not a semi-join. An inner join is different because it produces one row per matched row in table2. A semi-join only produces one row for each row in table1, even if it matches multiple rows in table2.
If you want to simulate a semi-join, use DISTINCT to reduce the result to one row per row of table1:
SELECT DISTINCT table1.*
FROM table1
JOIN table2 ON table1.id = table2.column
If you want to check for something like NOT EXISTS, use an exclusion join:
SELECT table1.*
FROM table1
LEFT OUTER JOIN table2 ON table1.id = table2.column
WHERE table2.column IS NULL
No need to use DISTINCT on the outer join example. There will be no row duplication from the join, because it can only "match no rows" once.

Select everything from joined tables

I have two joined tables:
SELECT table1.*, table2.* FROM table1 t1 INNER JOIN table2 t2 ON t1.id = t2.t1_id
The question: In query results, id will always be taken from secondary table defined in SELECT statement?
For example:
if I use select t1.*, t2.* - in results id will be t2.id
if I use select t2.*, t1.* - id will be t1.id.
Is this good practice to use 'merged' result, or should I avoid ambiguity, and always define columns strictly?
No, the sql query will return all columns with the same name from all tables, not just the last one, unless you use a natural join (table1 inner join table2 using(column)).
If you use some kind of a component that stores the results in associative arrays, then these components usually use only the field names as key, therefore they return only the last column's value from those that have the same name.
However, it is a good practive to use an alias if you want to return more than 1 column that has the same name in the database.
My suggestion is to use tablename with alias and get to use like this. It would be best practice to run query.Mention your column names even though it has many columns. You can order your display.
SELECT t1.columnName1, t2.columnName2 FROM tablename1 t1 INNER JOIN tablename2 t2 ON t1.id = t2.id

Update with nested subquery (sum) to get restricton on update clause

Got this bit of SQL as an update script, I've tried to add a work round to not being able to include the table to be updated as a clause in the statement so using sub queries, but struggling to get this to work.
Essientially I need update a vailue in table 1 with the summation of a field in table 2, but only where the two other fields match across a couple of tables and based on field6 the restriction is applied to the update clause.
UPDATE table1 W SET Field1=(SELECT field2 FROM
(SELECT A.id, B.field3, SUM(A.field2) AS field2
FROM table2 A, table3 B, table4 P
WHERE A.id=B.id AND P.field6=B.field6) B ) WHERE W.field6=B.field6
In the real world example, select the sum of points conceded in a rugby game when a rugby player has participated in the match. table 2 has the results (including the score) table 3 has the team sheets and table 1 and 4 are the same player table to be updated.
Hopefully this is clear enough and someone can point me in the right direction.
Tried the following:
UPDATE $WSLKEEP W, $WSLFIX A, $WSLFIXPLAY B
SET W.F_CONCEDED=SUM(A.F_AGAINST)
WHERE A.F_ID=B.F_GAMEID
AND B.F_NAME=W.F_NAME"
but now stuck with:
Invalid use of group function
Kind regards
It seems like your subquery should be grouping on field6 and exposing that column for inner join with table1. Here's how you do that in MySQL:
UPDATE table1 W
INNER JOIN (
SELECT B.field6, SUM(A.field2) AS field2
FROM table2 A, table3 B, table4 P
WHERE A.id=B.id AND P.field6=B.field6
GROUP BY B.field6
) B ON W.field6=B.field6
SET W.Field1 = B.Field2
And while we are at it, I would also recommend you to refrain from (ab)using comma joins in favour of explicit joins. The latter, however unusual at first after being long accustomed to a different syntax, can very soon become habitual and much more intuitive than the former. A great deal has been said on the topic, and some people may be holding quite strong opinions about comma joins. I say, comma joins can still have their share of use. However, when you are joining on a condition, the current ANSI syntax should be your choice.
Here's the above statement with the subquery transformed so as to use explicit joins:
UPDATE table1 W
INNER JOIN (
SELECT B.field6, SUM(A.field2) AS field2
FROM table2 A
INNER JOIN table3 B ON A.id = B.id
INNER JOIN table4 P ON P.field6 = B.field6
GROUP BY B.field6
) B ON W.field6 = B.field6
SET W.Field1 = B.Field2
For an update query like you have above, you are allowed to include multiple tables in the UPDATE clause, even if you aren't updating all of them. This will make sub-queries unnecessary and speed the execution quite a bit. For example, you can do something like this.
UPDATE table1 W, table2 A, table3 B, table4 P
SET W.Field1 = SUM(A.field2) ...
I'm unclear on the specifics of what you are trying to update exactly, but I just wanted to put out that you can often avoid sub-queries by using this kind of syntax.

inner join for a query?

I want to do a sql query and have some problems:
I want to salect from table_1 the ID's Where parent_id is the value I have:
SELECT ID FROM table_1 WHERE parent_ID = 'x'
I want to use the ID'S I got in 1. and
SELECT FROM table_2 WHERE ID = 'The ID's from Query 1.
Simple and Execute
Select t1.`id` FROM table t1 INNER JOIN table t2 ON t1.`id`=t2.`id`
As Bainternet mentioned you can do this with a subquery
SELECT * FROM table_2 WHERE ID IN (SELECT ID FROM table_1 WHERE parent_ID = 'x')
Though your idea to use an inner join is also good (especially since MySQL can be slow when processing subqueries).
SELECT t2.* FROM table_2 as t2 INNER JOIN table_1 AS t1 ON t2.ID = t1.ID WHERE t1.parent_ID = 'x'
If that's not clear, try looking at the MySQL JOIN Syntax or the Subqueries, as Bainternet mentioned. If these examples and the MySQL docs aren't clear enough for you, consider posting more details on exactly what you're trying to do (e.g. include table structures in your question). Also while you might want this information for some WordPress related work you are doing, there's nothing in the question itself that actually ties it to WordPress. So if you have more questions that about MySQL queries in general, then you might want to consider posting them to the StackOverflow, tagged as mysql-query.

MySql View - Value from one column where some other column is max

I have Table1 and Table2 related on Table1.ID. There can be zero or more Table2 records for a given Table1.ID. I have a view where I want to get Table2.Value where Table2.ID is max for a given Table1.ID. A friend suggested a derived table, but that requires a subquery in the from clause, and MySQL doesn't like that. Are there any other ways to do this? I tried setting up a secondary view to take the place of the subquery, but it seems very slow. I also tried using a having clause to test Table2.ID = MAX(Table2.ID), but it doesn't recognize the column unless I put it into the group by, which screws everything else up.
SELECT t1.*, t2a.*
FROM Table1 t1
LEFT JOIN Table2 t2a
ON (t1.table1_id = t2a.table1_id)
LEFT JOIN Table2 t2b
ON (t1.table1_id = t2b.table1_id AND t2a.table2_id < t2b.table2_id)
WHERE t2b.table2_id IS NULL
AND t1.table1_id = ?;