SQL Lower Bound? - mysql

I would like to write a sql query that returns all values greater than or equal to x and also the first value that is not greater than x.
For example if we have a table containing values 1, 2, 3, 4, 5 and x is 3, I need to return 2, 3, 4, 5.
The fact that my example includes evenly spaced integers does not help because my actual data is not as cooperative.
Is this even possible or am I better off just getting the entire table and manually figuring out which rows I need?

SELECT <columns> -- you want in the result
FROM tableX
WHERE columnX >=
( SELECT MAX(columnX)
FROM tableX
WHERE columnX < #x -- #x is the parameter, 3 in your example
) ;

union is your best bet. paste together the set of all values greater than x, and the largest value less than x. Something like the following should work:
SELECT n FROM table WHERE n > $x ORDER BY n DESC
UNION SELECT n from table WHERE n < $x ORDER By n DESC LIMIT 0,1;

SELECT * FROM MyTable WHERE MyColumn >= 3
UNION
SELECT * FROM MyTable WHERE MyColumn < 3 ORDER BY MyColumn DESC LIMIT 1

Related

How to find the most common value across multiple columns

I was just wondering what MySQL code could I use to find the most common value across a series of columns containing similar values.
SELECT `column`,
COUNT(`column`) AS `value_occurrence`
FROM `my_table`
GROUP BY `column`
ORDER BY `value_occurrence` DESC
LIMIT 1;
I know I can use the above code to the find most common value in a single column but how would I expand this to find the value in 3 columns?
Eg
Column 1: 1, 2, 2, 4
Column 2: 1, 3, 2, 1
Column 3: 1, 2, 2, 2
Result : 2
Use UNION to move all the columns into a single column.
SELECT col, COUNT(*) AS value_occurrence
FROM (
SELECT col1 AS col
FROM my_table
UNION ALL
SELECT col2 AS col
FROM my_table
UNION ALL
SELECT col3 AS col
FROM my_table) AS x
GROUP BY column
ORDER BY value_occurrence DESC
LIMIT 1
All you have to do is replace column in COUNT(column) with an asterisk (*). That is the universal selector for accessing all records of a table. Then in your ORDER BY clause, specify allColumns as the scope of the data you want to order it by.
select allColumns, count(*) as value_occurrence from dataTable
group by allColumns
order by value_occurrence desc, allColumns
LIMIT 1;

Select random records from mysql

In table X there's a field Y (int) which holds values from 1 to 8.
I'm trying to find the most efficient way to create a query (which is part of a stored procedure) which can select a random 5 records from the DB.
The 5 records are not random over the entire table - for example the procedure should be able
to select 1 random record where Y=1 another 2 records where Y=2 and another 2 records where Y in (4,5,6).
Is there a recommended way to achieve it or should I just use Union?
This query needs to be as fast as possible.
Union should be the fastest way to do that
(select * from your_table where Y = 1 order by rand() limit 1)
union
(select * from your_table where Y = 2 order by rand() limit 2)
union
(select * from your_table where Y in (4,5,6) order by rand() limit 2)

MYSQL select rows starting from a random number

I want to select 30 rows (in serial order) from anywhere in the middle of the table.
I am trying to do it by adding a column 'serial' having unique auto_increment serial numbers.
My code is:
SELECT * FROM A2
WHERE serial>(
SELECT ROUND(RAND()*(
SELECT COUNT(*) FROM A2))
) LIMIT 30
The part (SELECT ROUND(RAND()*(SELECT COUNT(*) FROM A2))) is working perfectly i.e. generates a random number from 1 till the number of rows in the table, but the complete query is not working. It throws rows that are not in serial progression, and it almost always throws first row having serial below 30.
Can someone help me to write this query.
Thanks
This should work, assuming your serial starts at 0; if it starts at 1, just replace >= with >.
SELECT A2.*
FROM A2
JOIN (SELECT FLOOR(RAND() * (SELECT COUNT(*)-29 FROM A2)) serial) b
WHERE a2.serial >= b.serial
ORDER BY a2.serial
LIMIT 30;
An SQLfiddle to test with.
Try this
SELECT * FROM A2 ORDER BY RAND() LIMIT 30
This will pick 30 random rows.
Append ORDER BY serial like this:
SELECT *
FROM A2
WHERE serial > (
SELECT ROUND(RAND() * (
SELECT COUNT(*) FROM A2)))
ORDER BY serial
LIMIT 30;
Also you probably need to use FLOOR instead of ROUND and subtract 30 from upper limit like this:
WHERE serial > (
SELECT FLOOR(RAND() * ((SELECT COUNT(*) FROM A2) - 30)))
Otherwise you may get less then 30 rows when random is close to the end of the table.
Sorry. That answer was wrong. Here is what works for me:
SELECT a2.*
FROM a2,
(SELECT FLOOR(RAND() * ((SELECT COUNT(*) FROM a2) - 30)) AS r) AS r
WHERE a2.serial BETWEEN r.r AND r.r + 29;
I would just do this
SELECT * FROM A2
WHERE serial > (
SELECT ROUND(RAND()*(SELECT COUNT(*) FROM A2))
)
ORDER BY serial
LIMIT 30

MySQL, SELECT * FROM t WHERE c={The most duplicated entry}

Pretty much as the title says, that was the simplest way I could explain it. To elaborate...
I first need to find the value of column c that has been duplicated the most times (mostDuplicated), and then SELECT * FROM t WHERE c=mostDuplicated
To go on about it further...
Here's my data:
SELECT * FROM t
a, b, c
- - -
1, 1, 1
2, 2, 1
3, 3, 1
4, 4, 2
5, 5, 3
So ignore the values in columns a & b completely, just concentrate on column c. I need to find the most duplicated value in column c (which is 1), and then SELECT only these records WHERE c=1. I want to do this in a single query if possible.
Do a "group by" query to count the number of unique values of c, order it descending and select only the top row. Then use the output as a subquery to select rows with that particular value of c:
SELECT * FROM t WHERE c = (SELECT c FROM t GROUP BY c ORDER BY COUNT(*) DESC LIMIT 1)
SELECT c FROM t GROUP BY c ORDER BY count(*) DESC LIMIT 1
Well it will be, like this:
SELECT * FROM t WHERE c =
(SELECT c FROM
(SELECT c, count(c) as co
FROM t ORDER BY co DESC LIMIT 1))
Hope this help
Here you go, it's a bit convoluted:
SELECT
*
FROM
t
WHERE
(
c IN
(
SELECT c
FROM (
SELECT
c,
COUNT(c) as freq
FROM
t
GROUP BY
c
ORDER BY
freq DESC,
c ASC
LIMIT 1
) AS t2
)
)
Basically, it's going this:
1. determine how often each value of C is repeated
2. select the value of the MAXimum repeats
3. use that value to determine what value of C to use when select * from the entire table.

two slightly different queries into one - use a conditional var?

Instead of executing 2 slightly different sql statements to get a total of 10 results can it be done with just one select?
e.g
select
a
, b
, c
from mytable limit 3
select
a
, b
, LEFT(100, c )
from mytable limit 3, 10
Check out UNION syntax
(SELECT a,b,c FROM mytable LIMIT 3)
UNION
(SELECT a,b,LEFT(100, c) FROM mytable LIMIT 3, 10);
Note the parentheses - these ensure the final LIMIT clause applies to the second query and not the whole result set.
Unless you've got a numeric key in the result which would let you use an IF to format the first n results differently, I don't think you're going to do this with a single select.
You can select all ten rows and then use a case statement to control what value is returned depending on a conditional statement you define.
set #line_total= 0;
select
a,
b,
#line_total := #line_total + 1,
(case when #line_total < 4
then c
else left(100, c) end)
from test_query limit 10;
http://dev.mysql.com/doc/refman/5.0/en/case-statement.html