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.
Related
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.
I am using GROUP_CONCAT in my query to collect some IDs. Imagine I have two columns as follow:
user_id
item
The code looks like this:
SELECT user_id, GROUP_CONCAT(item) AS all_items_by_user
FROM table
GROUP BY user_id
However, I noticed that the all_items_by_user column can accommodate up to a certain number of characters in each cell. This limit is around 1100 in my case, whereas I expect at least 10 times more. I wondered whether there is any way to increase this limit?
Thank you.
This is controlled by group_concat_max_len, a system variable.
The documentation describes how to change the value and what it really means.
I have a message id which i get when i search a text across all my chats. Once i click on it I go into that chat and now I want the messages that where around that message i.e 10 messages before and after. How do i get this limit done
The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement.
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.
SELECT * FROM tbl LIMIT 1,10; # Retrieve rows 1-10
You would have to know how many rows there are in total messages to implement correctly in your case
The alternative is using the limit with offset Define OFFSET for the query. For example
SELECT column FROM table LIMIT 10 OFFSET 10;
You could work out the total records with a server side language and then divide by the offset to work out how many iterations queries you need to perform
...
An alternative is to get all the records and page it with client side language like JS using something like pagination or a similar technique
I'm using MySQL to store financial stuff, and using the data to build, among other things, registers of all the transactions for each account. For performance reasons - and to keep the user from being overwhelmed by a gargantuan table - I paginate the results.
Now, as part of the register, I display a running balance for the account. So if I'm displaying 20 transactions per page, and I'm displaying the second page, I use the data as follows:
Transactions 0 - 19: Ignore them - they're more recent than the page being looked at.
Transactions 20 - 39: Select everything from these - they'll be displayed.
Transactions 40 - ??: Sum the amounts from these so the running balance is accurate.
It's that last one that's annoying me. It's easy to select the first 40 transactions using a LIMIT clause, but is there something comparable for everything but the first 40? Something like "LIMIT -40"?
I know I can do this with a COUNT and a little math, but the actual query is a bit ugly (multiple JOINs and GROUP BYs), so I'd rather issue it as few times as possible. And this seems useful enough to be included in SQL - and I just don't know about it. Does anybody else?
The documentation says:
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, with these
exceptions:
Within prepared statements, LIMIT parameters can be specified
using ? placeholder markers.
Within stored programs, LIMIT parameters can be specified using
integer-valued routine parameters or local variables as of MySQL
5.5.6.
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
To retrieve all rows from a certain offset up to the end of the result
set, you can use some large number for the second parameter. This
statement retrieves all rows from the 96th row to the last:
SELECT * FROM tbl LIMIT 95,18446744073709551615;
Next time, please use the documentation as your first port of call.
You can hack it this way:
select sel.*
from
(
SELECT #rownum:=#rownum+1 rownum, t.*
FROM (SELECT #rownum:=0) r, YourTableOrYourSubSelect t
) sel
where rownum > 40
It's kinda like having Oracle's rownum in MySQL.
In MySQL, how can I retrieve ALL rows in a table, starting from row X? For example, starting from row 6:
LIMIT 5,0
This returns nothing, so I tried this:
LIMIT 5,ALL
Still no results (sql error).
I'm not looking for pagination functionality, just retrieving all rows starting from a particular row. LIMIT 5,2000 seems like overkill to me. Somehow Google doesn't seem to get me some answers. Hope you can help.
Thanks
According to the documentation:
To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter. This statement retrieves all rows from the 96th row to the last:
SELECT * FROM tbl LIMIT 95, 18446744073709551615;
This is the maximum rows a MyISAM table can hold, 2^64-1.
There is a limit of 2^32 (~4.295E+09) rows in a MyISAM table. If you build MySQL with the --with-big-tables option, the row limitation is increased to (2^32)^2 (1.844E+19) rows. See Section 2.16.2, “Typical configure Options”. Binary distributions for Unix and Linux are built with this option.
If you're looking to get the last x number of rows, the easiest thing to do is SORT DESC and LIMIT to the first x rows. Granted, the SORT will slow your query down. But if you're opposed to setting an arbitrarily large number as the second LIMIT arg, then that's the way to do it.
The only solution I am aware of currently is to do as you say and give a ridiculously high number as the second argument to LIMIT. I do not believe there is any difference in performance to specifying a low number or a high number, mysql will simply stop returning rows at the end of the result set, or when it hits your limit.
I think you don't need to enter max value for select all by LIMIT. It is enough to find count of table and then use it as max LIMIT.
The next query should work too, and is in my opinion more effective...
SELECT * FROM mytbl WHERE id != 1 ORDER BY id asc
By ordering the query will find the id imediately and skip this one, so the next rows he won't check anymore whether the id = 1.