There is a words table with 20000 records:
ID name rank
1 word1 3
2 word2 5019
3 word3 12334
4 word4 23
5 word5 544
I want to select 400 words randomly from this table but with this condition :
first 20 words: select 20 words randomly from words with rank between 1 and 1000
second 20 words: select 20 words randomly from words with rank between 1000 and 2000
And so on...
Do I have to do this in 20 separate queries? How? Is there a better way?
I am using laravel 5.4 and Mysql, Also a raw query suggestion would be appreciated. Thank you
Easy way
use a where clause to filter their rank, then use inRandomOrder() and take(20) to get 20 random ones.
Word::inRandomOrder()->where('rank', '>=', 1)->where('rank', '<=', 1000)->take(20);
Hard way
To get them all in one query, you might try some funky logic like this:
first: define a view that returns the same table, but instead of rank, has categories, so category 1 for 1<=rank<1000, .... just to make the next step easier
now we can use partition by (see Trying to understand over() and partition by). Remember to order by RAND() inside the partition. Order the result of all this by rownumber.
Now we have a result that looks like this:
rownumber name category
1 word1 1
1 word2 2
1 word3 3
1 word4 4
...
2 word21 1
2 word22 2
2 word23 3
2 word24 4
...
20 word381 1
20 word382 2
20 word383 3
20 word384 4
...
By taking 400 of these tuples, we will have 20 random samples of each of the 20 categories.
Note-- ordering by RAND() can be slow, as explained here http://www.titov.net/2005/09/21/do-not-use-order-by-rand-or-how-to-get-random-rows-from-table/
Edit: turn out partition by is for sql server only. But you could do something similar in mysql
Related
I want to show top 3 results and if is there are any results which match with top 3, they should also be fetched. In the examples below there are top 3 results, 50,40 and 30, but ram also has a mark of 30, so I want to fetch that result as well.
my database sheet table
id
user
marks
1
ram
30
3
sam
30
4
ben
40
2
hari
10
5
joe
50
i want to return top 3 results along with all matching results which is match to last result
id
user
marks
5
joe
50
4
ben
40
3
sam
30
1
ram
30
$top_results = "SELECT * FROM `sheet` ORDER BY `marks` DESC LIMIT 3"
and it only return top 3 not the 4 results
i want to show top 3 results and if is there any results match with top 3 also fetched, in above case there is top 3 results are 50,40 and 30 but ram has also 30. So I want to fetch that result also if it is their along with top 3
I want to show top 3 results and if is there are any results which match with top 3, they should also be fetched.
SELECT t1.*
FROM table t1
JOIN ( SELECT result
FROM table t2
ORDER BY result DESC LIMIT 2,1 ) t3 ON t1.result >= t2.result
how to get top 5 results from database along with all matched results
Adjust LIMIT accordingly - LIMIT 4,1.
This question already has an answer here:
Ranking the results in mysql (mysql equivalents for 'dense_rank()' or 'row_number()' functions in oracle)
(1 answer)
Closed 4 years ago.
This is my table data
prod_id category_id
1 1
2 2
3 2
4 3
5 3
6 3
Expected result
prod_id category_id seq_no
1 1 1
2 2 1
3 2 2
4 3 1
5 3 2
6 3 3
This is just one of the sample to generate sequence number based on category, it might be other condition as well.
I am trying to generate sequence number for each group of data i get based on id_category field. I tried dense_rank() method but it is not supported for MySQL.
How can i generate sequence number for each group in this way?
DENSE_RANK() OVER (ORDER BY id_category) As seq_no
My query
Product::leftJoin('category','category.id_category','=','product.id_category')
........
->get();
If you don't have huge amounts of data, it's probably easiest to
grab everything
group by category
sort each category by product
loop through each category and set the sequence number based on the current index
While I don't know the exact nature of your tables, it would look something like this, with your query as the start:
Product::leftJoin('category','category.id_category','=','product.id_category')
->get()
->groupBy('category_id')
->each(function ($group) {
$group->sortBy('product_id')
->map(function ($product, $index) {
$product->seq_no = $index + 1;
});
});
Though note that this should be treated as pseudocode and adapted as fits your application best.
I already searched but I always find LEAST and GREATEST as hints. I want to have the next ascending number in a row that's not used. Like the following:
entries
1
2
3
5
6
7
If every of the numbers is for one row in my table I want the number 4 as a result and in the following example:
1
2
3
4
5
6
I want the number 7 as a result. Is there any possiblity to accomplish this in an SQL statement?
Best,
Robin
This query assumes that the number 1 is in your table
select min(number) + 1 from entries e1
where not exists (
select 1 from entries e2
where e2.number = e1.number + 1
)
If you want all missing numbers (where gaps are no larger than 1) instead of the smallest one, then remove min()
It think the solution is to do a self-join with the next value, and extract the first lowest result. Example:
Table: values, with column value
SELECT v1.value
FROM values v1
LEFT JOIN values v2 ON v1.value = (v2.value + 1)
WHERE v2.value IS NULL
ORDER BY v1.value ASC
LIMIT 1
I'm generally pretty self reliant on fudging something together that works but I have run into a brick wall on this one and am eventually reaching out for a nod in teh right direction..
my query:
$post_views = (int)$wpdb->get_var("
SELECT SUM(count) AS views
FROM ".$wpdb->prefix."post_views
WHERE id IN (".$post_id.") AND type = 0"
The database table looks like this :
id type period count
------- ------- ----------- -------
32310 0 20141023 8
32310 0 20141022 68
32310 1 201443 76
32310 2 201410 76
32310 3 2014 76
32310 4 total 76
The type 0 are the ones I'm interested in, I just want the sum of the COUNT column for the most recent 7 type 0 entries
I have been trying with things based around "ORDER BY period DESC LIMIT 7 " on the end of the query - to no avail, I generally get returns of 0 doing this.
a new type 0 row will be generated for each article every day, so thats why I need to only get the last 7
any help here would be massively appreciated, totally stuck for the first time ever with this.
SELECT SUM(count)
FROM (SELECT count
FROM wp_post_views
WHERE type = 0
AND id IN (684,42,7)
ORDER BY period DESC
LIMIT 7)
Or just determine the date a week ago first and use that to filter, but a subquery like this will work fine as well.
I have this table:
id track_name datetime weight
1 aName 2010-06-01 09:00:00 1
2 theName3 2010-07-01 11:00:00 2
3 heyThere 2010-08-01 16:00:00 3
4 abcd 2010-08-01 22:44:00 4
5 g123go 2010-08-01 22:00:50 5
6 foobar 2010-09-01 13:11:00 6
7 barfoo 2010-11-01 12:00:55 7
8 barbar 2010-12-01 11:11:00 8
The weight determines the row record order. It is used for ordering a playlist. And the user can move items up and down, thus reordering in the simple fashion, in which works great.
Now I wonder if there is possible to write a single query that can change the 'weight' value based on the 'date' column, ordering by either DESC or ASC. The same for the 'track_name' column.
Example pseudo query:
UPDATE table SET weight (start from 1) ORDER BY datetime ASC
My alternative is to fetch all rows and process each and everyone of them on the web server, which I doubt is the most effecient way, if there are thousands of records.
I don't think you can do it with a single query. You need a counter, this means you need a loop. If you want to do it with MySQL only, you can create a stored procedure. If not, just write a PHP script (witch might will be a bit slower). Logic is the same:
Get all the data from the table;
Loop through every record in the
order you need and update weight
parameter.
You could use a temporary table with an auto incremented id and select insert into it using your order.