Please explain this mysql query. - mysql

SELECT * FROM dogs order by rand(dayofyear(CURRENT_DATE)) LIMIT 1
It seems to me that it orders a database by a random number, and this number changes every day. This is a guess, as it'll take me a day to find out if this is true!
How can I change this query to order a database by a new random number every minute rather than every day? I tried this:
SELECT * FROM dogs order by rand(minuteofhour(CURRENT_DATE)) LIMIT 1
but it didn't work :(
Thanks for your time!

A random number generator (RNG) usually needs a 'seed value', a value that is used to generate random numbers. If the seed value is always the same, the sequence of random numbers is always the same. This explains why it changes every day.
The easiest way to solve your problem (change it to every minute) is to find a seed value that changes every minute. A good one would be ROUND(UNIX_TIMESTAMP()/60).
SELECT * FROM dogs order by rand(ROUND(UNIX_TIMESTAMP()/60)) LIMIT 1

I am not good at mysql. but are you sure is there a function minuteofhour in mysql?
The idea of query is to pick a random record from database.
you can do this by:
SELECT * FROM dogs order by rand(20) LIMIT 1
it will order by column "a random number from 1-20"

Use combo of MySQL's funcs MINUTE() and NOW(). NOW will return current date, and MINUTE extracts minute value from it.

Related

MySQL: in designing a loot drop table, is it possible to specify a number of times the query repeats itself and outputs each result on the same table

as part of teaching myself SQL, I'm coding a loot drop table that I hope to use in D&D campaigns.
the simplest form of the query is:
SELECT rarity,
CASE
WHEN item=common THEN (SELECT item FROM common.table)
WHEN item=uncommon THEN (SELECT item FROM unommon.table)
...etc
END AS loot
FROM rarity.table
ORDER BY RAND()*(1/weight)
LIMIT 1
the idea is that the query randomly chooses a rarity from the rarity.table based on a weighted probability. There are 10 types of rarity, each represented on the rarity.table as a single row and having a column for probabilistic weight.
If I want to randomly output 1 item (limit 1), this works great.
However, attempting to output more than 1 item at a time isn't probabilistic in that the query can only put out 1 row of each rarity. If say I want to roll 10 items (limit 10) for my players, it will just output all 10 rows, producing 1 item from each rarity, and never multiple of the higher weighted rarities.
I have tried something similar, creating a different rarity.table that was 1000 rows long, and instead of having a 'weight' column representing probabilistic weight in rows, ex. common is rows 1-20, uncommon rows 21-35...etc.
Then writing the query as
ORDER BY RAND()
LIMIT x
-- (where x is the number of items I want to output)
and while this is better in some ways, it results are still limited by the number of rows for each rarity. I.E. if I set limit to 100, it again just gives me the whole table without taking probability into consideration. This is fine in that I probably won't be rolling 100 items at once, but feels incorrect that the output will always be limited to
20 common items, 15 uncommon, etc. This is also MUCH slower, as my actual code has a lot of case and sub-case statements.
So, my thought moved on to if is possible to run the query with a limit 1, but to set the query to run x number of times, and then include each result on the same table, preserving probability and not being limited by the number of rows in the table. However, I haven't figured out how to do so.
Any thoughts on how to achieve these results? Or maybe a better approach?
Please let me know if I can clarify anything.
Thank you!
A big no-no is having several virtually identical tables (common and uncommon) as separate tables. Instead, have one table with an extra column to distinguish the types. That will let your sample query be written more simply, possibly with a JOIN.
attempting to output more than 1 item at a time isn't probabilistic in that the query can only put out 1 row of each rarity
Let's try to tackle that with something like
SELECT ... WHERE ... 'common' ORDER BY ... LIMIT 1
UNION
SELECT ... WHERE ... 'uncommon' ORDER BY ... LIMIT 1
...
If you don't want the entire list like that, then do
(
((the UNION above))
) ORDER BY RAND() LIMIT 3; -- to pick 3 of the 10
Yes, it looks inefficient. But ORDER BY RAND() LIMIT 1 is inherently inefficient -- it fetches the entire table, shuffles the rows, then peels off one row.
Munch on those. There are other possibilities.
while I'm sure there is room for improvement / optimization, I actually figured out a solution for myself in case anyone is interested.
Instead of the first query being the rarity table, I made a new table that is thousands of entries long, called rolls.table, and first query this table. Here, the limit function works as a way to select the number of rolls I want to make.
Then, every time this table outputs a row the query selects from the rarity.table independently.
Does that make sense?
I'll work with this for now, but would love to hear how to make it better.... it takes like 20 seconds for the output table to load haha.

MySQL Select cheapest latest ASK price

Guys i have this structure in a table:
The table holds a history of prices for set of Market Links connected to Exchanges. The data is continuously growing - every x seconds new prices are added.
I need to find out which MarketLink is currently the cheapest (ASK price)
What should be the query?
You need to order your result by latest time ie. epoch
SELECT id,MarketLink,MIN(Ask) from tbl_name ORDER by epoch DESC LIMIT 0 ;
I think this is what you're looking for. Hope it helps you out.
SELECT MIN(Ask) cheapest from tbl_name;
EDIT
In order to achieve this, You'll have to keep track of the records that you've already scanned, say for example you can use ID or a timestamp, every time you query. So while querying, what you're supposed to do is, use that ID or a timestamp as a benchmark and check for the Min(Ask) after that Id or timestamp.

SQL MIN() selecting Data. ORDER table correctly

I have 2 questions. First of all I have a MySQL Database with the rows: id(AUTO_INCREMENT PRIMARY KEY), name and time. This database represents the times of a race. I would like to select the name and time where the time is the smallest.
SELECT name, MIN(time) as time FROM race GROUP BY TIME;
This query gives me all times and names as long as there are no duplicates in the names. I however only want the fastest time and the name in that row.
Then when I submit my time i would like to know on what place I am. Will ORDER BY TIME keep each ID of each row the same or can I just ORDER table BY time and then select row where ID= 1?
If it's possible to have multiple entries with the same time, I would use a nested query like this, because limiting the result set to 1 may exclude a name.
select name, time from race where time = (select min(time) from race)
If you want to know what place a given time is in, just count the number of entries that have times less than it.
select count(*) + 1 as place from race where time < [your time]
For your first question, what you want is to select the 'least' time.
Here is, what I think, the clearest way to do that, which uses the LIMIT function to only return 1 row.
MySQL:
SELECT name, time
FROM race
ORDER BY time asc
LIMIT 1;
MS SQL:
SELECT TOP 1 name, time
FROM race
ORDER BY time asc

Using Coldfusion DateDiff within a MySQL Query?

I've spent a few hours playing around with this one, without success so far.
I'm outputting a very large query, and trying to split it into chunks before processing the data. This query will basically run every day, and one of the fields ('last_checked') will be used to ensure the same data isn't processed more than once a day.
Here's my existing query;
<cfquery name="getprice" maxrows="100">
SELECT ID, source, last_checked, price
FROM product_prices
WHERE source='api'
ORDER BY ID ASC
</cfquery>
I then run a cfoutput query on the results to do various updates. The table currently holds just over 100,000 records and is starting to struggle to process everything in one hit, hence the need to split it into chunks.
My intention is to cfschedule it to run every so often (I'll increase the maxrows and probably have it run every 15 minutes, for example). However, I need it to only return results that haven't been updated within the last 24 hours - this is where I'm getting stuck.
I know MySQL has it's own DateDiff and TimeDiff functions, but I don't seem to be able to grasp the syntax for that - if indeed its applicable for my use (docs seem to contradict themselves in that regard - or, at the least the ones I've read).
Any pointers very much appreciated!
Try this with MySQL first:
SELECT ID, source, last_checked, price
FROM product_prices
WHERE source='api'
AND last_checked >= current_timestamp - INTERVAL 24 HOUR
ORDER BY ID ASC
I would caution you against using maxrows=100 in your cfquery. This will still return the full recordset to CF from the database, and only then will CF filter out all but the first 100 rows. When you are dealing with a 100,000 row dataset, then this is going to be hugely expensive. Presumably, your filter for only the last 24 hours will dramatically reduce the size of your base result set, so perhaps this won't really be a big problem. However, if you find that even by limiting your set to those changed within the last 24 hours you still have a very large set of records to work with, you could change the way you do this to work much more efficiently. Instead of using CF to filter your results, have MySQL do it using the LIMIT keyword in your query:
SELECT ID, source, last_checked, price
FROM product_prices
WHERE source='api'
AND last_checked >= current_timestamp - INTERVAL 1 DAY
ORDER BY ID ASC
LIMIT 0,100
You could also easily set between "pages" of 100 rows by adding the offset value before the LIMIT: LIMIT 300, 100 would be rows 300-400 from your result set. Doing the paging this way will be much faster than offloading it to CF.

Selecting X oldest date from the database

Good Afternoon
Please can someone help me, I’m nearly a total noob. I have a very simple DB which has thousands of rows and very few columns. I have an ID, Name, Image, Information, and Date Added. Really basic!
Now I’m trying to display only a single row of data at a time so there is no need for loops and things in this request. Sounds very simple in theory?.
I can display a row in date order, and by the most recent or oldest, ascending or descending. But I want to be able to display for example: =
The 6th newest entry. And perhaps somewhere else on my sites the 16 most recent entry and so on. This could even be the 1232 most recent entry.
Sounds to me like it would be a common task but I can’t find the answer anywhere. Can someone provide me with the very short command for doing this? I probably missing something really daft and fundamental.
Thanks
Leah
The LIMIT clause can be used to constrain the number of rows returned by
the SELECT statement. LIMIT takes one or two numeric arguments, which
must both be nonnegative integer constants (except when using prepared
statements).
With two arguments, the first argument specifies the offset of the first
row to return, and the second specifies the maximum number of rows to
return. The offset of the initial row is 0 (not 1):
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
http://dev.mysql.com/doc/refman/5.1/en/select.html
So if you want the 1232nd row from your table you can something like this:
SELECT * FROM tbl ORDER BY date_added LIMIT 1231,1;
In your query use LIMIT e.g.
LIMIT 6,1 // Starts at row 6 and retrieves one result.