In MySQL, what does this simple nested SELECT clause mean exactly? - mysql

Here is the example from this thread:
select (
select distinct Salary from Employee order by Salary Desc limit 1 offset 1
)as second;
The select(...) as second looks confusing to me because I've never seen a query-set instead of column names can be used as the argument of SELECT..
Does anyone have ideas about how to understand nested select clause like this? Is there any tutorials about this feature?

That's a subquery in the SELECT list of a query.
To get there, let's look at some other examples
SELECT t.id
, 'bar' AS foo
FROM mytable
WHERE ...
LIMIT ...
'bar' is just a string literal that gets returned in every row (in a column named foo) in the resultset from the query.
Also, MySQL allows us to run a query without a FROM clause
SELECT 'fee' AS fum
We can also put a subquery in the SELECT list of a query. For example:
SELECT t.id
, (SELECT r.id FROM resorts r ORDER BY r.id ASC LIMIT 1) AS id
FROM mytable
WHERE ...
LIMIT ...
The query pattern you asked about is a SELECT statement without a FROM clause
And the only expression being returned is the result from a subquery.
For example:
SELECT e.salary
FROM Employee e
GROUP BY e.salary
ORDER BY e.salary DESC
LIMIT 4,1
If this query runs, it will return one column, and will return either one or zero rows. (No more than one.) This satisfies the requirements for a subquery used in a SELECT list of another query.
SELECT ( subquery ) AS alias
With that, the outer query executes. There's no FROM clause, so MySQL returns one row. The resultset is going to consist of one column, with a name of "alias".
For each row returned by the outer query, MySQL will execute the subquery in the SELECT list. If the subquery returns a row, the value of the expression in the SELECT list of the subquery is assigned to the "alias" column of the resultset. If the execution of the subquery doesn't return a row, then MySQL assigns a NULL to the "alias" column.

Related

SQL OrderBy Clause Not Working with max alias

I have a query
Select tableA.*, max(`queue_position`) AS `product_advertisements.queue_position`
from tableA join tableB
group by tableA.attribute
order by `product_advertisements.queue_position` ASC
When the query runs, its not actually sorting by the queue position,
This is my return https://gyazo.com/471749b349d64e94707b9452d4b25417,
This is the expected output, https://gyazo.com/e8c92b2898a404781c9de095f1146143
Does it have something to do with ordering by the joined attribute? Why is my order by clause being ignored completely
I do not know the name of all columns, but I guess there is a column with the same name "product_advertisements.queue_position", and you do not want to order by it. Instead, you want to order by MAX(queue_position)
Try these 2 options:
Use the MAX column as the first column, and "ORDER BY 1", it would apply the order clause to the first column.
Select max(queue_position) AS product_advertisements.queue_position, tableA.*
from tableA join tableB
group by tableA.attribute
order by 1 ASC;
Use "max(queue_position)" in the ORDER CLAUSE
Select tableA.*, max(queue_position) AS product_advertisements.queue_position
from tableA join tableB
group by tableA.attribute
order by max(queue_position) ASC
Anyway, why do you select all columns (tableA.*), but group only by one? MySQL accepts it, but in other Databases it is not allowed.

Re-write a nested mysql query so as to create a view

I have a nested query. Any suggestion on how i can rewrite the nested query so that I am able to create a view with it
Here is the query
select *
from (select * from tracking_table order by id desc) x
group by labref);
There doesn't seem to be any need for the nested query. It can just be:
SELECT *
FROM tracking_table
GROUP BY labref
ORDER BY id DESC
But both queries probably don't do what you want. All the columns will be chosen from unpredictable rows in each group, and there's no guarantee that different columns will come from the same row. You're also not guaranteed to get the highest ID in each group.
If you want the row with the highest ID for each labref, see SQL select only rows with max value on a column

MySQL 5.7 How to do GROUP BY with sorting?

Similar to this issue: MySQL 5.7 group by latest record
I'm not sure how to do this properly in 5.7. Also with possibility of 2nd sort column. Working query in 5.6 that I'm trying to replicate in 5.7:
SELECT id FROM test
GROUP BY category
ORDER BY sort1 DESC, sort2 DESC
id is not always the highest, so MAX(id) does not work.
Looking into the link above, the solution for single sort should be:
SELECT t1.*
FROM test t1
INNER JOIN (
SELECT category, max(sort) AS sort FROM test GROUP BY category
) t2 ON t2.category = t1.category AND t2.sort = t1.sort
But how will it work with 2 sorting?
You are using GROUP BY the wrong way.
Think of group by as a way to separate data row into different groups. Each group has multiple rows, based on the value of group by column.
Once you get those groups, selecting table columns (as in: select *) is like picking any row from that group randomly. This is not helpful nor useful.
Usually once we group records (or rows), we need to find meta information about those records. For example: get us the count of records in that group (as in: select count(*)), or the sum of values of a specific column in that group (as in: select sum(price)), or get the min, max or avg values.
So in a nutshell, when you use group by you should use on of the aggregation functions with it, otherwise it's not going to do you any good.
Why don't you have the ORDER BY at your outer query, instead?
SELECT *
FROM (
SELECT 100 AS id, 1 AS category, NULL AS sort
UNION
SELECT 200 AS id, 1 AS category, 2 AS sort
) dt
GROUP BY category
ORDER BY sort DESC;
It seems that what happened to the data when it was grouped, it took the first data while neglecting the ORDER BY DESC. On your first query, it ordered descending first then group by took the first record which is 200. And yes, this shouldn't be the way you should use GROUP BY. It is used in conjunction with aggregate functions.
when you select a column in a group by query that is not one of the columns you are grouping by, (ie, your id) you have no control over the value unless you use another aggregate function. If you want to sort, use MIN or MAX:
SELECT MAX(id), category, FROM `test2`
GROUP BY category; -- always returns 200
SELECT MIN(id), category, FROM `test2`
GROUP BY category; -- always returns 100

Finding duplicate rows in MySQL, this query should fail but it returns something: what?

In Oracle it would fail, since hr_descr2 has one dozen of column the query is not ANSI valid, but on MySQL it returns a resultset, but not the one I was expecting. I thought it to be similar to the resultset returned by the second query, but it seems more like a select *
select *
from hr_descr2 ds2
group by ds2.titolo
having count(1) > 1
order by titolo;
select titolo, count(1)
from hr_descr2 ds2
group by ds2.titolo
having count(1) > 1
order by titolo;
I was expecting the query to do this:
SELECT
*
FROM
hr_descr2
WHERE
titolo IN (SELECT
titolo
FROM
hr_descr2 ds2
GROUP BY ds2.titolo
HAVING COUNT(1) > 1)
ORDER BY titolo;
Since you indicate that the first query works, I will assume that the hr_descr2 table only has a single column: titolo. Otherwise, it should throw an error because of a non-aggregate value used with a group by.
Therefore, it returns a list of distinct titolo values which are duplicated and tells you how many times they occur.

How to get unsorted result from a select query that uses an 'in'?

below is the query i have.
select * from tblQuestionTable where Paper='HTML' and QuestionId in (select QuestionId from tblTestOverview where TestId=1)
The sub query gives an unsorted result set, but the after querying the second select the result is sorted. How can i get the result in the same order as the subquery.
Any dataset your query is working with is by default unordered, whether it is a physical table or a derived one. Whatever order the server uses to read rows from it while actually executing the query is out of your control. That means you cannot reliably specify the order to be "same as in that subquery". Instead, why not just have a specific order in mind and specify it explicitly in the main query with an ORDER BY? For instance, like this:
SELECT *
FROM tblQuestionTable
WHERE Paper='HTML'
AND QuestionId IN (SELECT QuestionId FROM tblTestOverview WHERE TestId=1)
ORDER BY QuestionId
;
Having said that, here's something that might be close to what you are looking for. The ROW_NUMBER function assigns row numbers to the derived dataset in an undetermined order (ORDER BY (SELECT 1)). It may or may not be the order in which the server has read the rows, but you can use the assigned values to order the final result set by:
SELECT q.*
FROM tblQuestionTable AS q
INNER JOIN (
SELECT
QuestionId,
rn = ROW_NUMBER() OVER (ORDER BY (SELECT 1))
FROM tblTestOverview
WHERE TestId = 1
) AS o
ON o.QuestionId = q.QuestionId
ORDER BY o.rn ASC
;
select result for tblQuestionTable will be sorted based on its primary index by default unless specified. tblTestOverview select result also does the same. So you need to include the primary index key feild from tblTestOverview table in the select query for tblQuestionTable and specify an order by clause based on that field.