Is this valid syntax? It seems like the from clause should be implied when explicitly naming the table and column, table.column.
SELECT
distinct concat(\"Question \", q.place) as question
FROM q
INNER JOIN test
ON test.id = q.test
AND q.id NOT IN (
SELECT responses.question
where //Is this Valid or do I need to select from a table explicitly?
responses.tester = tester.id)
INNER JOIN test
ON test.id = testingsession.test
INNER JOIN tester
ON tester.test = test.id
WHERE
tester.id = :id
ORDER BY
questions.position
In MySQL it's valid to have a SELECT without a FROM clause, but that returns singleton row (similar to using the special DUAL table from Oracle) and you can't use a WHERE clause.
In your case, the SELECT query is returning values from a table, so you need a FROM clause to reference that table.
To answer your question, no, what you have is not valid.
NOTES:
For performance, I'd use an anti-join pattern over a NOT IN (correlated_subquery).
There's several problems in the syntax:
You've got the test table referenced twice. At least one of those references is going to be assigned an alias.
You've got a reference to testingsession.test, but there is no testingsession row source in your query.
The query references questions.positions in the ORDER BY clause, but there is no questions row source.
That is not valid! You cannot use a column from a table that is not included in your FROM / JOIN part (here responses.tester). You will have to join responses too.
Related
What is the internal order of operations in a MySQL SELECT query and a relational query?
For instance, a SELECT query to a single table:
SELECT `name`
FROM `users`
WHERE `publication_count`>0
ORDER BY `publication_count` DESC
I know that at first all table fields are fetched and then only name field is left at the end. Does it happen before or after the condition in WHERE is applied? When is ORDER BY applied?
A relational query using two tables:
SELECT `users`.`name`, `post`.`text`
FROM `users`, `posts`
WHERE `posts`.`author_id`=`user`.`id`
ORDER BY `posts`.`date` DESC
Same question. What happens after what? (I know that at first the Cartesian product is generated)
Processing regarding your example simplifying the rules goes as follow:
1. FROM -- all elements in list (including multiple tables)
2. WHERE -- discard rows not matching conditions
3. SELECT -- output rows are computed (not fetched)
4. ORDER BY -- sort output rows
Also, you shouldn't be using old-fashioned implicit join syntax in WHERE condition. Instead, please use JOIN:
SELECT ...
FROM users
INNER JOIN posts ON users.id = posts.author_id
ORDER BY ...
I have simplified the query I am firing for brevity as follows
SELECT
1 AS mae
FROM
(SELECT
t.id
FROM transaction t) a
LEFT OUTER JOIN
(SELECT
track_id
FROM attendee) AS b ON a.id = b.track_id
HAVING mae > 0;
Over here there is no aggregation. However, I still have to use having. If I use where, mysql is unable to recognize the column mae.
Why is this so?
In general, aliases defined in the SELECT clause are not available for re-use in the same SELECT -- nor in the WHERE, nor in the ON clauses. This is a true of all SQL dialects. Aliases are allowed in the ORDER BY, on the other hand.
MySQL recognizes column aliases in the HAVING clause. This is so convenient that MySQL has extended the HAVING clause for use with non-aggregation queries. So, your query is using this extension.
One nice feature of this extension is that it allows the reference without using a subquery -- the normal way around this. Because MySQL materializes (almost) all derived tables, this saves overhead in the processing.
Ae you just trying to do a regular join ?
SELECT *
FROM transaction t
JOIN attendee AS b
ON a.id = b.track_id
The following query works just fine. I am using a value from the outer select to filter inside the inner select.
SELECT
bk.ID,
(SELECT COUNT(*) FROM guests WHERE BookingID = bk.ID) as count
FROM
bookings bk;
However, the following select will not work:
SELECT
bk.ID,
(SELECT SUM(count) FROM (SELECT COUNT(*) AS count FROM guests WHERE BookingID = bk.ID GROUP BY RoomID) sub) as sumcount
FROM
bookings bk;
The error message is: Error Code: 1054. Unknown column 'bk.ID' in 'where clause'
Why is my alias bk known in the subselect, but not in the subselect of the subselect?
For the record, I am using MySQL 5.6.
This is called "scoping". I know that Oracle (for instance) only looks out one level for resolving table aliases. SQL Server is also consistent: it looks out more than one level.
Based on this example, MySQL clearly limits the scope of the identifier bk to the immediate subquery. There is a small hint in the documentation (emphasis mine):
A correlated subquery is a subquery that contains a reference to a
table that also appears in the outer query.
However, I have not found any other specific reference to the scoping rules in the documentation. There are other answers (here and here) that specify that the scope of a table alias is limited to one level of subquery.
You already know how to fix the problem (your two queries should produce identical results). Re-arranging the query to have joins and aggregations can also resolve this problem.
Correlated Scalar Subqueries in the SELECT list can usually be rewritten to a LEFT JOIN on a Derived Table (and in many cases they might perform better then):
SELECT
bk.ID,
dt.sumcount
FROM
bookings bk
LEFT JOIN
(SELECT BookingID,SUM(COUNT) AS sumcount
FROM
(
SELECT BookingID, RoomId, COUNT(*) AS COUNT
FROM guests
GROUP BY BookingID, RoomID
) sub
) AS dt
ON bk.BookingID = dt.BookingID
This question already has answers here:
INNER JOIN ON vs WHERE clause
(12 answers)
Difference between these two joining table approaches?
(4 answers)
Closed 8 years ago.
I have a table Person with a column id that references a column id in table Worker.
What is the difference between these two queries? They yield the same results.
SELECT *
FROM Person
JOIN Worker
ON Person.id = Worker.id;
and
SELECT *
FROM Person,
Worker
WHERE Person.id = Worker.id;
There is no difference at all.
First representation makes query more readable and makes it look very clear as to which join corresponds to which condition.
The queries are logically equivalent. The comma operator is equivalent to an [INNER] JOIN operator.
The comma is the older style join operator. The JOIN keyword was added later, and is favored because it also allows for OUTER join operations.
It also allows for the join predicates (conditions) to be separated from the WHERE clause into an ON clause. That improves (human) readability.
FOLLOWUP
This answer says that the two queries in the question are equivalent. We shouldn't mix old-school comma syntax for join operation with the newer JOIN keyword syntax in the same query. If we do mix them, we need to be aware of a difference in the order of precedence.
excerpt from MySQL Reference Manual
https://dev.mysql.com/doc/refman/5.6/en/join.html
INNER JOIN and , (comma) are semantically equivalent in the absence of a join condition: both produce a Cartesian product between the specified tables (that is, each and every row in the first table is joined to each and every row in the second table).
However, the precedence of the comma operator is less than that of INNER JOIN, CROSS JOIN, LEFT JOIN, and so on. If you mix comma joins with the other join types when there is a join condition, an error of the form Unknown column 'col_name' in 'on clause' may occur. Information about dealing with this problem is given later in this section.
Beside better readability, there is one more case where explicitly joined tables are better instead of comma-separated tables.
let's see an example:
Create Table table1
(
ID int NOT NULL Identity(1, 1) PRIMARY KEY ,
Name varchar(50)
)
Create Table table2
(
ID int NOT NULL Identity(1, 1) PRIMARY KEY ,
ID_Table1 INT NOT NULL
)
Following query will give me all columns and rows from both tables
SELECT
*
FROM table1, table2
Following query will give me columns from first table with table alias called 'table2'
SELECT
*
FROM table1 table2
If you mistakenly forget comma in comma-separated join, second table automatically convert to table alias for first table. Not in all cases, but there is chances for something like this
Using JOINS makes the code easier to read, since it's self-explanatory.
In speed there is no difference (I tested it) and the execution plan is the same
If the query optimizer is doing its job right, there should be no difference between those queries. They are just two ways to specify the same desired result.
The SELECT * FROM table1, table2, etc. is good for a couple of tables, but it becomes exponentially harder as the number of tables increases.
The JOIN syntax makes it explicit what criteria affects which tables (giving a condition). Also, the second way is the older standard.
Although, to the database, they end up being the same
I'd like do something like this:
In table TAGS find a row with name='someName', and remeber it's id
In the same table find another row with someCondition and set in this row col refference=the id from above
Tried to do this using a subquery, but mysql refused saying I can't subquery a table that I'm updating in the main query.
How can I otherwise implement the above idea?
Thank you
Convert your subquery to a join and then UPDATE:
You can also perform UPDATE operations covering multiple tables. However, you cannot use ORDER BY or LIMIT with a multiple-table UPDATE. The table_references clause lists the tables involved in the join. Its syntax is described in Section 12.2.8.1, “JOIN Syntax”. Here is an example:
UPDATE items,month SET items.price=month.price
WHERE items.id=month.id;
The preceding example shows an inner join that uses the comma operator, but multiple-table
UPDATE statements can use any type of join permitted in SELECT statements, such as LEFT JOIN.
you can do this
update TAGS set
reference =
(select my_id from
(select id as my_id from TAGS where name='someName')
as SUB_TAGS)
where someCondition;
Not advisable though.
Edit#1 You can avoid the sub-queries altogether -- as taspeotis rightly mentioned, by joining the same table with the criteria. Here goes the code for that:
UPDATE
TAGS t1, TAGS t2
SET
t1.reference = t2.id
WHERE
t2.name = 'someName'
AND
t1.someField = someCondition;
This is a better approach.