How to sort results from UNION - mysql

I have a query like this:
(select #number:=3)
union
(select #number:=2)
union
(select #number:=1)
order by #number ASC
With results:
3
2
1
But I would like the results in ascending order, like this:
1
2
3
How can I achieve the results in ascending order with a query like this?

You can wrap the UNION in a subquery, try this:
SELECT *
FROM(
SELECT #number := 3 AS number
UNION
SELECT #number := 2 AS number
UNION
SELECT #number := 1 AS number) tmp
ORDER BY number;
Here is an SQL Fiddle example.
An edit, to explain what is happening:
In your example, MySQL is treating each group as its own query (which is how you'd expect a union to work) so it is as if you had three different queries, and only the third one is being ordered.
So, by putting the unioned queries together, you have one result set, and that entire result set is what is being ordered.

This is your query:
(select #number:=3)
union
(select #number:=2)
union
(select #number:=1)
order by #number ASC
Your order by has a constant. It is order by "1" -- #number is a variable, not a column name. Hence, no ordering. What you want is to specify the number as a column name:
select 3 as number
union all
select 2
union all
select 1
order by number;
You should also use union all instead of union, unless you want the additional overhead of removing duplicates.

Related

How to count the total number of results before a hyphen?

I am looking to count the number of results from a SQL count query, the results currently have like 50 results, but in reality there are only 5 results... the results appear in a format such as:
test1-helpme1
test1-helpme3
test1-helpme4
test2-helpme1
test2-helpme2
test3-helpme4
Is there a way I can count just the "testx-" part of the results?
There can be hundreds of results so the number part of "test" can't be hardcoded
SELECT COUNT(*) as CountbyID, OriginalId FROM Table1 GROUP BY OriginalId;
If you want the number of the distinct occurrences of the pattern, then:
SELECT
COUNT(DISTINCT LEFT(OriginalId, INSTR(OriginalId, '-') - 1)) as counter
FROM Table1
or a counter for each one:
SELECT
LEFT(OriginalId, INSTR(OriginalId, '-') - 1) pattern,
COUNT(*) as counter
FROM Table1
GROUP BY LEFT(OriginalId, INSTR(OriginalId, '-') - 1)
Yup you can use LEFT to group by a subset of the string:
declare #test as table (test varchar(100))
insert into #test
Select 'test1-helpme1' UNION ALL
Select 'test1-helpme3' UNION ALL
Select 'test1-helpme4' UNION ALL
Select 'test2-helpme1' UNION ALL
Select 'test2-helpme4'
Select count(*) as countbyID, left(test,5) as originalid from #test group by left(test,5)

Mysql group_concat split by count

Is it possible to perform a group_concat in mysql and have some sort of group limit? thus allowing the group to be split over a number of result rows?
e.g.
if I have a table called num like so:
val
---
1
2
3
4
5
...
and I use the statement select group_concat(val) from num
I get the result
1,2,3,4,5,...
What I want to do is set a group limit of 2 and get the result
1,2
3,4
5,...
Now the use case I have is hundreds of thousands of values that I want to select as neat groups of about 500.
Is it possible?
You can use a user variable to create a row number, then group by dividing the row numbers by the group size.
SELECT GROUP_CONCAT(val) AS vals
FROM (SELECT val, #rownum := #rownum + 1 AS rownum
FROM (SELECT val FROM nums ORDER BY val) AS vals
CROSS JOIN (SELECT #rownum := -1) AS vars) AS temp
GROUP BY FLOOR(rownum/500)

combine two results into one result set mysql

I have two queries one will return data ordered by likes and in the user city the other one return data by the distance .
so if query 1 return : id 1,2,3 (order by likes)
and query 2 return : id 4,5,6 (order by distance)
i need the final set results to be 1,2,3,4,5,6
i've tried to do union between the two queries but it's not working. any other suggestions ?
You can use left join or union according to this link.
Union ALL also works like you can see here.
Example: SELECT 1 UNION ALL SELECT 2
the solution was to put a limit to each query then the union will work correct :
(SELECT DISTINCT ID, 'a' as type,... FROM table1 GROUP BY ID ORDER BY likesDESC limit 50) union all( SELECT DISTINCT ID, 'b' as type,....FROM table1 GROUP BY ID ORDER BY distance limit 50) order by type asc.

Changing a Query with a numbered result set (with gaps,) to return result with no gaps, containing every number.

I have a select statement: select a, b, [...]; which returns the results:
a|b
---------
1|8688798
2|355744
4|457437
7|27834
I want it to return:
a|b
---------
1|8688798
2|355744
3|0
4|457437
5|0
6|0
7|27834
An example query that does not do what I would like, since it does not have the gap numbers:
select
sub.num_of_ratings,
count(sub.rater)
from
(
select
r.rater_id as rater,
count(r.id) as num_of_ratings
from ratings r
group by rater
) as sub
group by num_of_ratings;
Explanation of the query:
If a user rates another user, the rating is listed in the table ratings and the id of the rating user is kept in the field rater_id. Effectively I check for all users who are referred to in ratings and count how many ratings records I find for that user, which is rater / num_of_ratings, and then I use this result to find how many users have rated a given number of times.
At the end I know how many users rated once, how many users rated twice, etc. My problem is that the numbers for count(sub.rater) start fine from 1,2,3,4,5... However, for bigger numbers there are gaps. This is because there might be one user who rated 1028 times - but no user who rated 1027 times.
I don't want to apply stored procedures looping over the result or something like that. Is it possible to fill those gaps in the result without using stored procedures, looping, or creating temporary tables?
If you have a sequence of numbers, then you can do a JOIN with that table and fill in the gaps properly.
You can check out this questions on how to get the sequence:
generate an integer sequence in MySQL
Here is one of the answers posted that might be easily used with the limitation that generates numbers from 1 to 10,000:
SELECT #row := #row + 1 as row FROM
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t,
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t2,
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t3,
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t4,
(SELECT #row:=0) t5
Using a sequence of numbers, you can join your result set. For instance, assuming your number list is in a table called numbersList, with column number:
Select number, Count
from
numbersList left outer join
(select
sub.num_of_ratings,
count(sub.rater) as Count
from
(
select
r.rater_id as rater,
count(r.id) as num_of_ratings
from ratings r
group by rater
) as sub
group by num_of_ratings) as num
on num.num_of_ratings=numbersList.number
where numbersList.number<max(num.num_of_ratings)
Your numbers list must be larger than your largest value, obviously, and the restriction will allow it to not have all numbers up to the maximum. (If MySQL does not allow that type of where clause, you can either leave the where clause out to list all numbers up to the maximum, or modify the query in various ways to achieve the same result.)
#mazzucci: the query is too magical and you are not actually explaining the query.
#David: I cannot create a table for that purpose (as stated in the question)
Basically what I need is a select that returns a gap-less list of numbers. Then I can left join on that result set and treat NULL as 0.
What I need is an arbitrary table that keeps more records than the length of the final list. I use the table user for that in the following example:
select #row := #row + 1 as index
from (select #row := -1) r, users u
limit 101;
This query returns a set of the numbers von 0 to 100. Using it as a subquery in a left join finally fills the gap.
users is just a dummy to keep the relational engine going and hence producing the numbers incrementally.
select t1.index as a, ifnull(t2.b, 0) as b
from (
select #row := #row + 1 as index
from (select #row := 0) r, users u
limit 7
) as t1
left join (
select a, b [...]
) as t2
on t1.index = t2.a;
I didn't try this very query live, so have merci with me if there is a little flaw. but technically it works. you get my point.
EDIT:
just used this concept to gain a gapless list of dates to left join measures onto it:
select #date := date_add(#date, interval 1 day) as date
from (select #date := '2010-10-14') d, users u
limit 700
starts from 2010/10/15 and iterates 699 more days.

Counting word occurrences in a table column

I have a table with a varchar(255) field. I want to get (via a query, function, or SP) the number of occurences of each word in a group of rows from this table.
If there are 2 rows with these fields:
"I like to eat bananas"
"I don't like to eat like a monkey"
I want to get
word | count()
---------------
like 3
eat 2
to 2
i 2
a 1
Any idea? I am using MySQL 5.2.
#Elad Meidar, I like your question and I found a solution:
SELECT SUM(total_count) as total, value
FROM (
SELECT count(*) AS total_count, REPLACE(REPLACE(REPLACE(x.value,'?',''),'.',''),'!','') as value
FROM (
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(t.sentence, ' ', n.n), ' ', -1) value
FROM table_name t CROSS JOIN
(
SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
ORDER BY n
) n
WHERE n.n <= 1 + (LENGTH(t.sentence) - LENGTH(REPLACE(t.sentence, ' ', '')))
ORDER BY value
) AS x
GROUP BY x.value
) AS y
GROUP BY value
Here is the full working fiddle: http://sqlfiddle.com/#!2/17481a/1
First we do a query to extract all words as explained here by #peterm(follow his instructions if you want to customize the total number of words processed). Then we convert that into a sub-query and then we COUNT and GROUP BY the value of each word, and then make another query on top of that to GROUP BY not grouped words cases where accompanied signs might be present. ie: hello = hello! with a REPLACE
I would recommend not to do this in SQL at all. You're loading DB with something that it isn't best at. Selecting a group of rows and doing frequency calculation on the application side will be easier to implement, will work faster and will be maintained with less issues/headaches.
You can try this perverted-a-little way:
SELECT
(LENGTH(field) - LENGTH(REPLACE(field, 'word', ''))) / LENGTH('word') AS `count`
ORDER BY `count` DESC
This query can be very slow. Also, it looks pretty ugly.
I think you should do it like indexing, with additional table.
Whenever u create, update, or delete a row in your original table, you should update your indexing table. That indexing table should have the columns: word, and the number of occurrences.
I think you are trying to do too much with SQL if all the words are in one field of each row. I recommend to do any text processing/counting with your application after you grab the text fields from the db.