Select with UNION ALL and ORDER BY - mysql

I've trying to query from a few tables with UNION ALL but I get this error on the ORDER clause:
#1054 - Unknown column 'Time' in 'order clause'
I have column Time in the table. This is the query:
SELECT * from
(SELECT table, 'as' from as
UNION ALL
SELECT table, 'as' from as1
UNION ALL
SELECT table, 'as' from as2
UNION ALL
SELECT table, 'as' from as3) asAllWrong
WHERE table not like 'as%' OR length(table) < 12
ORDER BY Time='2015-06-02 9:00:00;
So, how exactly I can query this to show me all wrong entry from those tables and this table?
And why did I get this error even if there is a column called Time?
Edit: My mistake they are different tables as, as1, as2... And I want to query all wrong entries in that time as I said.
EDIT: This is what is look like now and is working good so far. Note that this is for me.. will not go in any production and will be used sometimes so I don't really need performance .. etc..
SELECT * from
( SELECT as.*, 'as' from as
UNION ALL
SELECT as1.*, 'as1' from as1
UNION ALL
SELECT as2.*, 'as2' from as2
UNION ALL
SELECT as3.*, 'as3' from as3) asAllWrong
WHERE as not like 'as%' OR length(as) < 12
ORDER BY Time='2015-06-02 9:00:00' ASC;

While the query looks very confusing, the bottom line is that your result in-memory table created via UNION ALL doesn't contain the field Time and that's why you have an error.
As for why it's not there, normally you can't just select {table_name}. It has to be a list of columns. But I am not an expert in MySql - it may allow such trickery. As Jonathan noted below, you'd be better of with:
select table.Time, 'as' from table
union all...
This would definitely bring Time field into the picture.

You need to specify also the Time column in your select
SELECT * from
(SELECT table, Time, 'as' from as
UNION ALL
SELECT table, Time, 'as' from as
UNION ALL
SELECT table, Time, 'as' from as
UNION ALL
SELECT table, Time, 'as' from as) asAllWrong
WHERE table not like 'as%' OR length(table) < 12
ORDER BY Time='2015-06-02 9:00:00' ASC/DESC;
This should work.
EDIT: Thank's for pointing my errors. I just use his example to show it.
Also as other said already you can user select as.*, 'as' from as... this will select all fields from as if you need them of course.
Also you may need ASC or DESC in your ORDER BY clause. ORDER BY sorts the records in ascending order by default.

Related

Inline queries in MySQL 5.6

Could someone please show me how to use an inline query in MySQL 5.6
I am trying to do a simple thing! I am trying to write a query in which I select from a table in database and join with an inline table that I am trying to create on the fly.
It's a 1 column table and I am having trouble creating it with multiple rows.
Example inline query
select * from (
(select 'filename1' as file_name) as t1
union
(select 'filename2' as file_name) as t2
);
If I run this query without the second select statement, then it works.
But if I run it with both select statements and try to union them it breaks down and complains that I have an error in SQL syntax near "as t2".
Any help is greatly appreciated.
Obviously a really over-simplified example, but... The members of a union query do not take aliases. The derived table that your are creating with union does take one, though. So:
select * from (
select 'filename1' as file_name
union all
select 'filename2'
) t;
Note that:
there is no need to surround the union members with parentheses (unless you want individual order by clauses)
there is no need to alias the column(s) in the second member: the aliases defined in the first query prevail anyway
unless you do want to remove duplicates, use union all instead of union: it is more efficient, and makes the intent explicit
Finally: as your query stands, there is no need for the outer query. This is equivalent:
select 'filename1' as file_name
union all
select 'filename2'
Bonus: in very recent versions of MySQL, you can use the values row() constructor:
select *
from (values row('filename1'), row('filename2')) t(filename)

Mysql DISTINCT with more than one column (remove duplicates)

My database is called: (training_session)
I try to print out some information from my data, but I do not want to have any duplicates. I do get it somehow, may someone tell me what I do wrong?
SELECT DISTINCT athlete_id AND duration FROM training_session
SELECT DISTINCT athlete_id, duration FROM training_session
It works perfectly if i use only one column, but when I add another. it does not work.
I think you misunderstood the use of DISTINCT.
There is big difference between using DISTINCT and GROUP BY.
Both have some sort of goal, but they have different purpose.
You use DISTINCT if you want to show a series of columns and never repeat. That means you dont care about calculations or group function aggregates. DISTINCT will show different RESULTS if you keep adding more columns in your SELECT (if the table has many columns)
You use GROUP BY if you want to show "distinctively" on a certain selected columns and you use group function to calculate the data related to it. Therefore you use GROUP BY if you want to use group functions.
Please check group functions you can use in this link.
https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html
EDIT 1:
It seems like you are trying to get the "latest" of a certain athlete, I'll assume the current scenario if there is no ID.
Here is my alternate solution:
SELECT a.athlete_id ,
( SELECT b.duration
FROM training_session as b
WHERE b.athlete_id = a.athlete_id -- connect
ORDER BY [latest column to sort] DESC
LIMIT 1
) last_duration
FROM training_session as a
GROUP BY a.athlete_id
ORDER BY a.athlete_id
This syntax is called IN-SELECT subquery. With the help of LIMIT 1, it shows the topmost record. In-select subquery must have 1 record to return or else it shows error.
MySQL's DISTINCT clause is used to filter out duplicate recordsets.
If your query was SELECT DISTINCT athlete_id FROM training_session then your output would be:
athlete_id
----------
1
2
3
4
5
6
As soon as you add another column to your query (in your example, the column called duration) then each record resulting from your query are unique, hence the results you're getting. In other words the query is working correctly.

SQL query - union on NOW()

I tried making a SQL query and union the result on the current time, but I cannot seem to find a neat way to solve this.
I've tried the following:
SELECT * FROM `accounts`
UNION SELECT NOW()
And Sequel Pro just reports The used SELECT statements have a different number of columns.
The accountstable just has three columns:
ID (INT(32), AUTO_INC)
CREATED (Timestamp)
NAME (VAR_CHAR(28))
I anticipated I'd get a response with four columns: ID, CREATED, NAME, NOW
What do I do wrong?
Union means that the records from the second query will be appended to those retrieved from the first one.
So the two tables must have the same structure for this to work.
For example:
SELECT field1,field2,field3 FROM tableA
UNION
SELECT field1,field2,field3 FROM tableB
What you want to do is
SELECT *, NOW() as now FROM `accounts`
This will retrieve all the records from the accounts table and will add the timestamp to all the rows on a column named "now" (this is just an alias so use whatever you like).
try this
SELECT *,now() as now FROM `accounts`

How to isolate a tuple from sql ordering while ordering the rest?

I searched for an answer here and didn't find one closer to my question.
I have the following situation: I need to display a person first and then show the rest in ascending order. All the people from the same table. I tried UNION but after that, the SQL seems to mix everything again.
I have tried this:
select name from people where name = 'John'
UNION
select name from people order by name
Since UNION does not select duplicated values. But in the end, it mixed up every result and did not show in the correct order that should be:
John
Ana
Bruce
What am I doing wrong?
You need to use order by to get what you want. In MySQL, this is pretty easy:
select name
from people
order by (name = 'John') desc, name
Results sets (like tables) represent unordered sets in SQL. The only way to impose an order is to use order by. The order by at the end of a union/union all query applies to the entire query.
As an aside, your code would come close to working if you used union all -- which is much preferred over union. The union operation does additional work to remove duplicates. In this case, that reorders the results, a convenient reminder that you can only depend on the order of results when you use order by.
Also you can use UNION ALL in a derived table
SELECT name
FROM
(
SELECT 1 AS Row_Id, name
FROM people
WHERE name = 'John'
UNION ALL
SELECT 2 AS Row_Id, name
FROM people
) t
ORDER BY Row_Id

MYSQL, Subquery Reference in Union

Is there any way to reference a subquery in a union?
I am trying to do something like the following, and would like to avoid a temporary table, but the subquery will be drawn from a much larger dataset so it makes sense to only do it once..
SELECT * FROM (SELECT * FROM ads WHERE state='FL' AND city='Maitland' AND page='home' ORDER BY RAND()) AS sq WHERE spot = 'full-banner' LIMIT 1
UNION
SELECT * FROM sq WHERE spot = 'leaderboard' LIMIT 1
UNION
SELECT * FROM sq WHERE spot = 'rectangle1' LIMIT 1
UNION
SELECT * FROM sq WHERE spot = 'rectangle2' LIMIT 1
.... etc,,
It's a shame that DISTINCT can't be specified for a single column of a result set.
Well, there is no way to do what you're trying to do without repeating the creation of the derived table.
If querying ads is really expensive then you should try adding an index like:
alter table ads add index (state, city, page, spot);
If after adding that index the query takes too much, then I'd recommend creating a table to store this data and then query that table for each spot.
Depending on your data, you could play around with GROUP BY to get similar results.