SQL - How to select discontinuous rows from a table with one select? - mysql

`SELECT * FROM Post
WHERE Tid = Id
ORDER BY Time
LIMIT 0,1`
`SELECT * FROM Post
WHERE Tid = Id
ORDER BY Time
LIMIT start,offset;`
Can I use only one SELECT to complete this?
Just like
`SELECT * FROM Post
WHERE Tid = Id
ORDER BY Time
LIMIT 0,1 and start,offset;`

In this case combine the 2 sql statements in a union, since you cannot provide multiple limit clauses in a single select:
SELECT * FROM Post LIMIT 1,2
UNION ALL
SELECT * FROM Post LIMIT 5,6;
However, I would add an order by clause to the 2 select statements just to make 100% sure you know which records will be selected.
UPDATE: Technically you could do this in a single statement using a running counter and filtering on the counter in where. However, that would not really be a good idea from performance wise, since mysql would have to loop through all records within the table. It cannot know which records would satisfy the criteria. Limit clauses are better optmised.

Related

How to Selecting 500 rows to be processed in meantime get the total rows in that table

is there a way to select couple columns using a limit but in mean time get the total count of rows in that table
SELECT col1,col2 FROM table where col3=0 limit 500
just like above. what to add to get the total of rows in the table
thank you
Try this, you only need to use one column in the count
SELECT COUNT(col3) FROM table where col3=0
And here's a reference for more information MySQL COUNT
Note, to keep it simple, you have to run two queries, this one for the count and yours for the records
Your question lacks a precise problem statement.
My understanding of your question is as follows:
All of the following is necessary:
Need to get every row from the table, such that col3=0.
Need to get the total number of rows in the table (whether they satisfy col3=0 or not).
Need to limit your result set to columns col1, col2, and have at most 500 rows.
Need to execute a single query, rather than two separate queries.
If this is correct interpretation of your question, then I would propose the following solution:
SELECT col1,col2, (SELECT COUNT(*) FROM table) AS total_rows FROM table where col3=0 limit 500
Such query would produce result where at most 500 rows from your table satisfy the condition col3=0 are present alongside total_rows, which tells the number of all the rows in the table.
Example CSV of the result:
clo1,col2,total_rows
a,b,1000
c,d,1000
d,e,1000
according to found_rows()
The SQL_CALC_FOUND_ROWS query modifier and accompanying FOUND_ROWS() function are deprecated as of MySQL 8.0.17; expect them to be removed in a future version of MySQL. As a replacement, considering executing your query with LIMIT, and then a second query with COUNT(*) and without LIMIT to determine whether there are additional rows
instead of these queries:
SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE id > 100 LIMIT 10;
SELECT FOUND_ROWS();
Use these queries instead:
SELECT * FROM tbl_name WHERE id > 100 LIMIT 10;
SELECT COUNT(*) FROM tbl_name WHERE id > 100;
COUNT(*) is subject to certain optimizations. SQL_CALC_FOUND_ROWS causes some optimizations to be disabled.
you can check these questions
how-to-get-number-of-rows
mysql-what-is-the-row-count-information-function-for-select

Why does SQL LIMIT clause returns random rows for every query?

It is a very simple query. For every query, I get a different result. Similar things happen when I used TOP 1. I would like a random sub-sample and it works. But am I missing something? Why does it return a different value every time?
SELECT DISTINCT user_id FROM table1
where day_id>="2009-01-09" and day_id<"2011-02-16"
LIMIT 1;
There's no guarantee that you will get a random result with your query. It's quite likely you'll get the same result each time (although the actual result returned will be indeterminate). To guarantee that you get a random, unique user_id, you should SELECT a random value from the list of DISTINCT values:
SELECT user_id
FROM (SELECT DISTINCT user_id
FROM table1
WHERE day_id >= "2009-01-09" AND day_id < "2011-02-16"
) u
ORDER BY RAND()
LIMIT 1
SQL statements represent unordered sets, add order by clause such as
...
ORDER BY user_id
LIMIT 1

Is there a way to do this query without the sub-select?

I'm not positive but I believe sub-selects are less than optimal (speedwise?).
Is there a way to remove this sub-select from my query (I think the query is self-explanatory).
select *
from tickers
where id = (select max(id) from tickers where annual_score is not null);
Would something like:
SELECT *
FROM ticker
WHERE annual_score IS NOT NULL
ORDER BY id desc
LIMIT 1
work?
That particular sub-select shouldn't be inefficient at all. It should be run once before the main query begins.
There are a certain class of subqueries that are inefficient (those that join columns between the main query and the subquery) because they end up running the subquery for every single row of the main query.
But this shouldn't be one of them, unless MySQL is severely brain-damaged, which I doubt.
However, if you remain keen to get rid of the subquery, you can order the rows by id (descending) and only fetch the first, something like:
select * from tickers
where annual_score is not null
order by id desc
limit 0, 1
Not too familiar with MySQL, but if you want to eliminate the subquery then you could try something like this:
select *
from tickers
where annual_score is not null
order by id desc
limit 1
I don't know if this is more or less performant as MySQL is not my background.

MySQL: Select statement and selectively retrieve data

I have a large dataset in MySQL and I would like to speed up the select statement when reading data. Assuming that there are 1000 records, I would like to issue a select statement that retrieves half of them for example but based on time-stamp.
Using something like this will not work, while id is not tightly coupled with time-stamp
select * from table where table.id mod 5 = 0;
Retrieving all the data and afterwards select the data needed is not a solution while I want to avoid retrieving the large dataset. Thus, I 'm looking for something that would distinguish the records upon select.
Thnx
If you need speed then try this
select * from table ORDER BY table.id DESC LIMIT 0,500;
select * from table ORDER BY table.id DESC LIMIT 500,500;
and so on...

How to optimize a MySQL query so that a selected value in a WHERE clause is only computed once?

I need to randomly select, in an efficient way, 10 rows from my table.
I found out that the following works nicely (after the query, I just select 10 random elements in PHP from the 10 to 30 I get from the query):
SELECT * FROM product WHERE RAND() <= (SELECT 20 / COUNT(*) FROM product)
However, the subquery, though relatively cheap, is computed for every row in the table. How can I prevent that? With a variable? A join?
Thanks!
A variable would do it. Something like this:
SELECT #myvar := (SELECT 20 / COUNT(*) FROM product);
SELECT * FROM product WHERE RAND() <= #myvar;
Or, from the MySql math functions doc:
You cannot use a column with RAND()
values in an ORDER BY clause, because
ORDER BY would evaluate the column
multiple times. However, you can
retrieve rows in random order like
this:
mysql> SELECT * FROM tbl_name ORDER BY
> RAND();
ORDER BY RAND() combined with LIMIT is
useful for selecting a random sample
from a set of rows:
mysql> SELECT * FROM table1, table2
> WHERE a=b AND c<d -> ORDER BY RAND()
> LIMIT 1000;
RAND() is not meant to be a perfect
random generator. It is a fast way to
generate random numbers on demand that
is portable between platforms for the
same MySQL version.
Its a highly mysql specific trick but by wrapping it in another subquery MySQL will make it a constant table and compute it only once.
SELECT * FROM product WHERE RAND() &lt= (
select * from ( SELECT 20 / COUNT(*) FROM product ) as const_table
)
SELECT * FROM product ORDER BY RAND() LIMIT 10
Don't use order by rand(). This will result in a table scan. If you have much data at all in your table this will not be efficient at all. First determine how many rows are in the table:
select count(*) from table might work for you, though you should probably cache this value for some time since it can be slow for large datasets.
explain select * from table will give you the db statistics for the table (how many rows the statistics thinks are in the table) This is much faster, however it is less accurate and less accurate still for InnoDB.
once you have the number of rows, you should write some code like:
pseudo code:
String SQL = "SELECT * FROM product WHERE id IN (";
for (int i=0;i<numResults;i++) {
SQL += (int)(Math.rand() * tableRows) + ", ";
}
// trim off last ","
SQL.trim(",");
SQL += ")";
this will give you fast lookup on PK and avoid the table scan.