I have data that looks like
id val
--------
1 1
2 1
3 1
4 2
5 2
6 2
7 3
8 3
9 3
I'd like to fetch the id (and value) of two randomly chosen rows for each value, something like:
id val
--------
2 1
3 1
4 2
6 2
8 3
9 3
[EDIT]
I use MySQL v5.7
[SOLUTION]
I finally found another solution to my problem which is more compact and more useful if for example I want to limit the results to 25 id per value
SELECT val, SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY RAND() SEPARATOR ','), ',', 2)
FROM my_table
GROUP BY val
The idea is to group by val, concatenate the corresponding id in a string and taking a substring of the desired length.
try this
SELECT t.val,
#id := (SELECT t2.id FROM tbl_values t2 WHERE t2.val=t.val ORDER BY RAND() LIMIT 1) id1,
(SELECT t2.id FROM tbl_values t2 WHERE t2.val=t.val and t2.id<>#id ORDER BY RAND() LIMIT 1) id2
FROM tbl_values t
GROUP by 1
db fiddle demo
With MySQL 8.0 you could use ROW_NUMBER():
SELECT id, val
FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY val ORDER BY RAND()) AS rn
FROM tab) sub
WHERE rn <=2;
DB-Fiddle.com Demo
How about something like:
SELECT val, MIN(id)
FROM data
GROUP BY val
Related
I have this query, which is nothing special but I don't think it's efficient at all. I want to select from a single table random rows with different where cases. So the result should be 1 random row with the specific type for each select like shown in the queries. Some of the "type" values can be the same but they should still return random result.
Select * from fruits where type = 1 order by RAND() limit 1
Select * from fruits where type = 1 order by RAND() limit 1
Select * from fruits where type = 3 order by RAND() limit 1
Select * from fruits where type = 4 order by RAND() limit 1
Select * from fruits where type = 4 order by RAND() limit 1
I would express this as:
select t.*
from (select t.*,
row_number() over (partition by type order by rand()) as seqnum
from t
) t join
(select 1 as type, 2 as n union all
select 3 as type, 1 as n union all
select 4 as type, 2 as n
) x
using (type)
where x.n <= seqnum
You can use ROW_NUMBER() window function with ORDER BY RAND() to assign a random ordering for the rows of each type.
Then select the number of rows you want for each type.
This will work in MySql:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY type ORDER BY RAND()) rn
FROM fruits
WHERE type IN (1, 3, 4)
) t
WHERE rn <= CASE type
WHEN 1 THEN 2 -- 2 rows for type = 1
WHEN 3 THEN 1 -- 1 row for type = 3
WHEN 4 THEN 2 -- 2 rows for type = 4
END
See a simplified demo.
if you are using Postgres:
select distinct on (type) type, *
from like_this
where type in ( 1,2,3,4,5)
order by type, random()
I'm trying to query a database but excluding the first and last rows from the table. Here's a sample table:
id | val
--------
1 1
2 9
3 3
4 1
5 2
6 6
7 4
In the above example, I'd first like to order it by val and then exclude the first and last rows for the query.
id | val
--------
4 1
5 2
3 3
7 4
6 6
This is the resulting set I would like. Note row 1 and 2 were excluded as they had the lowest and highest val respectively.
I've considered LIMIT, TOP, and a couple of other things but can't get my desired result. If there's a method to do it (even better with first/last % rather than first/last n), I can't figure it out.
You can try this mate:
SELECT * FROM numbers
WHERE id NOT IN (
SELECT id FROM numbers
WHERE val IN (
SELECT MAX(val) FROM numbers
) OR val IN (
SELECT MIN(val) FROM numbers
)
);
You can try this:
Select *
from table
where
val!=(select val from table order by val asc LIMIT 1)
and
val!=(select val from table order by val desc LIMIT 1)
order by val asc;
You can also use UNION and avoid the 2 val!=(query)
;WITH cte (id, val, rnum, qty) AS (
SELECT id
, val
, ROW_NUMBER() OVER(ORDER BY val, id)
, COUNT(*) OVER ()
FROM t
)
SELECT id
, val
FROM cte
WHERE rnum BETWEEN 2 AND qty - 1
What if you use UNION and exclude the val you don't want. Something like below
select * from your_table
where val not in (
select top 1 val from your_table order by val
union
select top 1 val from your_table order by val desc)
I have this table
id fruit
---------
1 apple
2 banana <--
3 apple
4 apple
5 apple
6 apple
7 banana <----
8 apple
9 banana
10 apple
And I want to select rows until 2 bananas are found, like
SELECT id FROM table_fruit UNTIL number_of_bananas = 2
So the result would be 1,2,3,4,5,6,7
How could I achieve this?
thanks
I wish I could give credits to all of you who answered my question. I'v tested all of them, and they all work perfectly (got the expected result).
Though answers of Devart and ypercube seem a little bit complex and difficult for me to understand.
And since AnandPhadke was the first one provided a working solution, I'll choose his answer as accepted.
You guys are awesome, thanks!
Try this query -
SELECT id, fruit FROM (
SELECT
b.*, #b:=IF(b.fruit = 'banana', 1, 0) + #b AS banana_number
FROM
bananas b,
(SELECT #b := 0) t
ORDER BY id) t2
WHERE
banana_number < 2 OR banana_number = 2 AND fruit = 'banana'
SQLFiddle demo
select * from tables where id <=
(
select id from (
select id from tables where fruit='banana'
order by id limit 2) a order by id desc limit 1
)
SQLFIDDLE DEMO
#Devart's answer is perfect but it's an alternative option to we can use:
SELECT * FROM table_fruit WHERE id <=
(
SELECT id FROM
(SELECT id FROM table_fruit WHERE fruit='banana' ORDER BY id LIMIT 2) a
ORDER BY ID DESC LIMIT 1
);
Or using MAX
SELECT * FROM table_fruit WHERE id <=
(
SELECT MAX(id) FROM
(SELECT id FROM table_fruit WHERE fruit='banana' ORDER BY id LIMIT 2) a
);
See this SQLFiddle
select * from table_fruit where id <=
(
select max(id) from
(select id from table_fruit where fruit='banana' order by id limit 2) t
)
If there are less than 2 rows with 'banana', this will return all rows of the table:
SELECT t.*
FROM table_fruit AS t
JOIN
( SELECT MAX(id) AS id
FROM
( SELECT id
FROM table_fruit
WHERE fruit = 'banana'
ORDER BY id
LIMIT 1 OFFSET 1
) AS lim2
) AS lim
ON t.id <= lim.id
OR lim.id IS NULL ;
I have two integer columns in a table where the first column is populated with some random numbers and the second column is empty. Now is it possible to sort the first column in ascending order and at the same time sort it in descending order and display as the second column? I have the example of the table below.
Initial Table:
col1 col2
5
7
3
9
2
Output:
col1 col2
2 9
3 7
5 5
7 3
9 2
Try this:
SELECT tb1.col1,tb2.col2 FROM
(SELECT #rownum:=#rownum+1 as rank, id as col1
FROM your_table, (SELECT #rownum:=0) as r
ORDER BY id ASC) as tb1
JOIN
(SELECT #rownum2:=#rownum2+1 as rank, id as col2
FROM your_table, (SELECT #rownum2:=0) as r
ORDER BY id DESC) as tb2
ON tb1.rank = tb2.rank
Okay i am trying to create a mysql query that does this:
show 3 random records from table then after the 3th record show TEXT
and then show the same 3 items but other field (equaling to the items ofcourse) from same table.
eg table info:
--ids | titles------
10 | one
20 | two
30 | three
and the query results from the given example:
30 10 20 TEXT three one two
if anyone understand what i am asking,post your suggestion/asnwer
thanks for your time all :)
Just for kicks..
select t1.id, t2.id, t3.id, 'TEXT', t1.title, t2.title, t3.title
FROM
(
select #r := #r + 1 rownum, id
from (select #r:=0) initvar, (
select id
from tbl
order by rand()
limit 3
) X
) Y
join tbl t1 on Y.rownum=1 and t1.id = Y.id
join tbl t2 on Y.rownum=2 and t2.id = Y.id
join tbl t3 on Y.rownum=3 and t3.id = Y.id
You should really just do the query below, and do whatever display processing using the 3 rows returned, in whatever programming environment you use (Java/PHP/.Net etc).
select id, title
from tbl
order by rand()
limit 3
EDIT
To get the data in 7 different rows, you can use the below. I stress again that this is front-end display code. I will not use such SQL code in a production system.
select display
from
(
select sorter, rownum,
case when sorter=3 then title else id end display
from
(
select #r := #r + 1 rownum, id, title
from (select #r:=0) initvar,
(
select id, title
from tbl
order by rand()
limit 3
) X
) Y, (select 1 sorter union all select 3) dup
union all
select 2, 0, 'TEXT'
) Z
order by sorter, rownum
Example Output
7
2
1
TEXT
test 7 << title for id=7
test 2
test 1