ORDER BY not working properly with UNION in MySQL - mysql

I have 2 tables t1 and t2 as follows
I want to select the results from both the tables with a UNION and sort on qty column. The query that I have written is
(SELECT * FROM t1)
UNION ALL
(SELECT * FROM t2)
ORDER BY qty ASC;
That gives me the below result
Can some 1 tell me what is going wrong here? As per the query I should get qty column sorted in ascending order. I have also tried
(SELECT * FROM t1
UNION ALL
SELECT * FROM t2)
ORDER BY qty ASC;
No luck with that either. If I do sort with id or item it works perfectly fine. This is really frustrating. Please help.

Possible duplicate of Sorting varchar field numerically in MySQL
Try
(SELECT * FROM t1
UNION ALL
SELECT * FROM t2)
ORDER BY CAST(qty as SIGNED INTEGER) ASC;

Related

Select multiple rows by position without id

In MySql I have a complex SELECT which returns a table of about 500k rows and without primary key.
I would like to select 10 rows based on the different position they have in the resulting table, as efficiently as possible.
I tried using LIMIT:
SELECT * FROM table_name LIMIT 5,1;
efficient but select only one row.
I tried with UNION and LIMIT, but I have to do the complex SELECT several times:
(SELECT * FROM table_name LIMIT 5,1)
UNION
(SELECT * FROM table_name LIMIT 1000,1)
UNION
(SELECT * FROM table_name LIMIT 50000,1)
...
Is there a more efficient way to get what I want?
In order to get the positions you must sort the data; there is no way around that. So, number your rows by the desired order and pick the positions you want:
select *
from
(
select t.*, row_number() over (order by ...) as rn
from table_name t
) numbered
where rn in (6, 1001, 50001);

How do i select the most recent datetime from 2 tables

I've searched around but can't find the answer I'm looking for.
I have two tables, each has a date field called last_update_date. I want to search which of the two tables has the most recent date and only return that date.
I tried this query hoping it will order the two tables last_update_date field and return that result but the query does not work. Any help would be appreciated.
"Select last_update_date from Table1, Table2 order by last_update_date DESC Limit 1"
SELECT MAX(last_update_date)
FROM (
SELECT MAX(last_update_date) as last_update_date
FROM Table1
UNION ALL
SELECT MAX(last_update_date)
FROM Table2
) tMax
select * from
( select last_update_date from table1
UNION ALL
select last_update_date from table2
) order by last_update_date;
SELECT MAX(A.last_update_date)
(SELECT last_update_date FROM Table1
UNION ALL
SELECT last_update_date FROM Table2) A;

Combining tables while changing id - SQL

I'm trying to create a search function in different tables using UNION and what happened is that the id's are duplicating making the search go wrong. How can I merge different tables into one while no id's are in common?
Here is the example
table1
id name desc
1 henry post
2 albert doth
3 jun cloth
table2
id name desc
1 kin revenge
2 pot eve
The result SHOULD be like this
id name desc
1 henry post
2 albert doth
3 jun cloth
4 kin revenge
5 pot eve
Please help me. Thanks.
In most databases, you would add a new id using the ANSI standard row_number() function:
select row_number() over (order by which, id) as newid, name, description
from (select 1 as which, t1.* from table1 t1 union all
select 2 as which, t2.* from table2 t2
) t;
Note that desc is a really bad name for a column, because it is a SQL keyword and usually a reserved word.
EDIT:
MySQL doesn't support this ANSI standard functionality. Instead, use variables:
select (#rn := #rn + 1) as newid, name, description
from (select 1 as which, t1.* from table1 t1 union all
select 2 as which, t2.* from table2 t2
) t cross join
(select #rn := 0) vars
order by which, id;
I've include the order by so the rows remain in the same order that you seem to want them in -- rows from the first table followed by rows from the second table. If you don't care about the order, just drop the order by.
For SQLite, the calculation is much more painful:
with cte as (
select 1 as which, t1.* from table1 t1 union all
select 2 as which, t2.* from table2 t2
)
select (select count(*)
from cte cte2
where cte2.which < cte.which or (ct2.which = cte.which and cte2.id <= cte.id
) as id,
name, description
from cte;
In MySql, you can simulate the row_number() function of Sql Server and Oracle using a mutating variable hack:
set #rownum := 0;
SELECT #rownum:=#rownum+1 AS` row_number`, `name`, `desc`
FROM
(
SELECT `name`, `desc` FROM table1
UNION
SELECT `name`, `desc` FROM table2
) AS x;
SqlFiddle
It looks like you have to Generate Id's so you can make you Union query as Sub select and generate Id's in Outer Query
MySQL does not have any system function like SQL Server’s row_number () to generate the row number for each row. However, it can be generated using the variable in the SELECT statement
SET #row_number:=0;
SELECT #row_number:=#row_number+1 As Id,
NAME,
desc
FROM (SELECT NAME,desc
FROM table1
UNION ALL
SELECT NAME,desc
FROM table2
UNION ALL
........
........) A
Order by NAME -- Change the column in Order by in which order you want to create New ID's

UNION two ordered MySQL statements

I have a table with 3 columns (id, name, code) and 10 rows. Some of the rows don't have a code so that column is empty for some. What I'm trying to accomplish is SELECT the rows with code column not empty first ordered by last inserted followed by all rows with code column empty ordered by last inserted.
I have tried
(SELECT * from tablename WHERE code <> '' ORDER BY ID DESC) UNION
(SELECT * from tablename WHERE code = '' ORDER BY ID DESC)
The UNION works but the order does not. I have read here about other questions and found out adding ORDER BY like I added will not work and I should add it at the end but that would not help me accomplish what I want and will mix rows that have a code with rows that don't.
Is there a way to succeed with what I'm looking for?
I think you just need to put your sort logic in the ORDER BY clause
SELECT id, name, code
FROM tablename
ORDER BY code = '', ID desc;
Try this:
SELECT * FROM
(
(SELECT * from tablename WHERE code <> '' ORDER BY ID DESC)
UNION
(SELECT * from tablename WHERE code = '' ORDER BY ID DESC)
)tab ORDER BY ID DESC;
Or
SELECT * from tablename ORDER BY code DESC,ID DESC
Change ASC/DESC as per you want it to show

MySQL select most occurring or average

I have a MySQL table from which I want to select:
1) Either "most occurring" value, if there is any prevailing
2) Or "average" value, if there is no most occurring value.
Example table 1:
value
1
2
3
4
All values are occurred equally, therefore I want to take AVG(`value`)
Example table 2:
value
1
2
2
3
Value 2 prevails, therefore I want to select the value 2.
What mysql query would do this?
Starting from Gordon's answer I tested and corrected the SQL query in SQL Fiddle:
SELECT IF(t4.numcnts = 1, t1.avgvalue, t2.topvalue) AS result
FROM (select avg(value) as avgvalue from test) t1
CROSS JOIN (select value as topvalue from test group by value order by count(*) desc limit 1) t2
CROSS JOIN join (select count(distinct cnt) as numcnts from
(select count(*) as cnt from test group by value) t3) t4
Here is the Fiddle with the two test tables (switch out test2 for test to see the result when a particular value prevails): http://sqlfiddle.com/#!2/76914/3
My changes were to use an IF instead of a CASEstatement in the SELECTclause and to add the necessary table aliases for the subselects.
The following approach calculates both values and then chooses between them:
select (case when numcnts = 1 then avgvalue else topvalue end)
from (select avg(value) as avgvalue from t) cross join
(select value as topvalue from t group by value order by count(*) desc limit 1) cross join
(select count(distinct cnt) as numcnts from (select count(*) as cnt from t group by value))
Note: if you have ties for the top, but other values as well, then an arbitrary value is returned. You don't specify what to do in this case.
Also, the SQL is untested, so it might have syntax errors.