Select second, third, fourth, fifth, largest number - php

I have a question about how to select the second, third, fourth, and fifth largest number in a table. To select the biggest row I use:
$max = SELECT max(money) FROM table
Right now I want to specify $second_max, $third_max, $fourth_max and $fifth_max.
Does someone know how to change my previous SQL select max() easy to specify second max, third max etc...?
I do not want to use:
select money from table order by money desc limit 5;
Because I want them all in different variables.

select money from table order by money desc LIMIT 5

Probably the easiest way is to get them on separate rows:
select t.money
from table t
group by t.money
order by money desc
limit 5;
The next easiest thing is to put them in a comma-separated list:
select group_concat(money order by money desc) as monies
from (select t.money
from table t
group by t.money
order by money desc
limit 5
) T

Just this:
SELECT money
FROM yourtable
ORDER BY money DESC
LIMIT 5
You'll get a 5-record result set, ordered by the top money values - assuming you actually have 5+ records in the table.

USE SQL
select money from table order by money desc limit 5;
The five rows are there as max, secondary,... value of money.

In ORACLE you could do the following :
SELECT *
FROM (
SELECT ADRESSID,
ROW_NUMBER() OVER (ORDER BY ADRESSID DESC) AS ROW_NUM
FROM ADRESSTABLE
) t
WHERE ROW_NUM = 1
OR ROW_NUM = 3
OR ROW_NUM = 5;

Related

Select most common value? [duplicate]

How can I find the most frequent value in a given column in an SQL table?
For example, for this table it should return two since it is the most frequent value:
one
two
two
three
SELECT
<column_name>,
COUNT(<column_name>) AS `value_occurrence`
FROM
<my_table>
GROUP BY
<column_name>
ORDER BY
`value_occurrence` DESC
LIMIT 1;
Replace <column_name> and <my_table>. Increase 1 if you want to see the N most common values of the column.
Try something like:
SELECT `column`
FROM `your_table`
GROUP BY `column`
ORDER BY COUNT(*) DESC
LIMIT 1;
Let us consider table name as tblperson and column name as city. I want to retrieve the most repeated city from the city column:
select city,count(*) as nor from tblperson
group by city
having count(*) =(select max(nor) from
(select city,count(*) as nor from tblperson group by city) tblperson)
Here nor is an alias name.
Below query seems to work good for me in SQL Server database:
select column, COUNT(column) AS MOST_FREQUENT
from TABLE_NAME
GROUP BY column
ORDER BY COUNT(column) DESC
Result:
column MOST_FREQUENT
item1 highest count
item2 second highest
item3 third higest
..
..
For use with SQL Server.
As there is no limit command support in that.
Yo can use the top 1 command to find the maximum occurring value in the particular column in this case (value)
SELECT top1
`value`,
COUNT(`value`) AS `value_occurrence`
FROM
`my_table`
GROUP BY
`value`
ORDER BY
`value_occurrence` DESC;
Assuming Table is 'SalesLT.Customer' and the Column you are trying to figure out is 'CompanyName' and AggCompanyName is an Alias.
Select CompanyName, Count(CompanyName) as AggCompanyName from SalesLT.Customer
group by CompanyName
Order By Count(CompanyName) Desc;
If you can't use LIMIT or LIMIT is not an option for your query tool. You can use "ROWNUM" instead, but you will need a sub query:
SELECT FIELD_1, ALIAS1
FROM(SELECT FIELD_1, COUNT(FIELD_1) ALIAS1
FROM TABLENAME
GROUP BY FIELD_1
ORDER BY COUNT(FIELD_1) DESC)
WHERE ROWNUM = 1
If you have an ID column and you want to find most repetitive category from another column for each ID then you can use below query,
Table:
Query:
SELECT ID, CATEGORY, COUNT(*) AS FREQ
FROM TABLE
GROUP BY 1,2
QUALIFY ROW_NUMBER() OVER(PARTITION BY ID ORDER BY FREQ DESC) = 1;
Result:
Return all most frequent rows in case of tie
Find the most frequent value in mysql,display all in case of a tie gives two possible approaches:
Scalar subquery:
SELECT
"country",
COUNT(country) AS "cnt"
FROM "Sales"
GROUP BY "country"
HAVING
COUNT("country") = (
SELECT COUNT("country") AS "cnt"
FROM "Sales"
GROUP BY "country"
ORDER BY "cnt" DESC,
LIMIT 1
)
ORDER BY "country" ASC
With the RANK window function, available since MySQL 8+:
SELECT "country", "cnt"
FROM (
SELECT
"country",
COUNT("country") AS "cnt",
RANK() OVER (ORDER BY COUNT(*) DESC) "rnk"
FROM "Sales"
GROUP BY "country"
) AS "sub"
WHERE "rnk" = 1
ORDER BY "country" ASC
This method might save a second recount compared to the first one.
RANK works by ranking all rows, such that if two rows are at the top, both get rank 1. So it basically directly solves this type of use case.
RANK is also available on SQLite and PostgreSQL, I think it might be SQL standard, not sure.
In the above queries I also sorted by country to have more deterministic results.
Tested on SQLite 3.34.0, PostgreSQL 14.3, GitHub upstream.
Most frequent for each GROUP BY group
MySQL: MySQL SELECT most frequent by group
PostgreSQL:
Get most common value for each value of another column in SQL
https://dba.stackexchange.com/questions/193307/find-most-frequent-values-for-a-given-column
SQLite: SQL query for finding the most frequent value of a grouped by value
SELECT TOP 20 WITH TIES COUNT(Counted_Column) AS Count, OtherColumn1,
OtherColumn2, OtherColumn3, OtherColumn4
FROM Table_or_View_Name
WHERE
(Date_Column >= '01/01/2023') AND
(Date_Column <= '03/01/2023') AND
(Counted_Column = 'Desired_Text')
GROUP BY OtherColumn1, OtherColumn2, OtherColumn3, OtherColumn4
ORDER BY COUNT(Counted_Column) DESC
20 can be changed to any desired number
WITH TIES allows all ties in the count to be displayed
Date range used if date/time column exists and can be modified to search a date range as desired
Counted_Column 'Desired_Text' can be modified to only count certain entries in that column
Works in INSQL for my instance
One way I like to use is:
select *<given_column>*,COUNT(*<given_column>*)as VAR1 from Table_Name
group by *<given_column>*
order by VAR1 desc
limit 1

PHP MySQL select two random rows but not with rand()

I need to select 2 random rows but it's known that rand() is too slow. So I tryed a code from a website and it is:
SELECT *
FROM bilder AS r1 JOIN
(SELECT (RAND() *
(SELECT MAX(id)
FROM bilder)) AS id)
AS r2
WHERE r1.id >= r2.id
ORDER BY r1.id ASC
LIMIT 2
But this way I get same 2 rows multiple times and parsing is also not correct, so this is complete useless. Is there a working solution which is better that rand()? The table name is bilder the fields are: id, userid, nickname. id is primary and auto increment. Some rows are also deleted so it's not 1 2 3 4 5 but 1 2 4 5 6... so the solution to generate random numbers and select them won't work
There are multiple solutions to this problem, but something like the following often has good enough performance:
SELECT b.*
FROM bilder b CROSS JOIN
(SELECT COUNT(*) as cnt FROM bilder) v
WHERE rand() <= 100 / cnt
ORDER BY rand()
LIMIT 2;
The subquery selects about 100 rows. Sorting such a small number of rows is usually pretty fast. It then chooses two of them.
The most likely cause of your consternation was failing to wrap the RAND() * (SELECT MAX(id) FROM bilder) in a call to CEIL(), resulting in a float instead of an integer:
SELECT *
FROM bilder AS r1 JOIN
(SELECT ceil(RAND() *
(SELECT MAX(id)
FROM bilder)) AS id)
AS r2
WHERE r1.id >= r2.id
ORDER BY r1.id ASC
LIMIT 2
There are much faster methods of choosing one random row. Both of these methods below choose only one random row. You asked for two random rows. But these methods are orders of magnitude faster than doing a table-scan, so it's worth using these methods even if it takes multiple tries to get a second distinct random row.
The fastest way is to do it in two queries (I'll show in pseudocode):
$max = SELECT MAX(id) FROM bilder
$rand1 = rand(1..$max)-1
SELECT * FROM bilder WHERE id > $rand1 LIMIT 1
$id1 = id of the first row chosen
$rand2 = rand(1..$max)-1
SELECT * FROM bilder WHERE id > $rand2 AND id <> $id1 LIMIT 1
$id2 = id of the second row chosen
if $id2 = $id1, then choose a new $rand2 and query again
The problem with this is that if there are large gaps due to deleted rows, you get a higher chance of choosing the row that follows the gap.
Another fast method if you don't update the table very often is to add a column for consecutive ordering, then assign sequential values to that column in random order:
ALTER TABLE bilder ADD COLUMN rank INT UNSIGNED, ADD KEY (rank);
SET #r := 0;
UPDATE bilder SET rank = (#r:=#r+1) ORDER BY RAND();
Do this ranking once. It will be slow. Then once the rows are ranked, you can pick random value(s) fast:
$max = SELECT MAX(rank) FROM bilder;
$rand1 = rand(1..$max)
$rand2 = rand(1..$max) until $rand2 != $rand1
SELECT * FROM bilder WHERE rank IN ($rand1, $rand2);
Of course if you add or delete any rows from the table, you have to renumber the rows. Or at least you can do this more efficiently:
If you insert, then insert the new row with a random value and update the rank of the existing row to $max+1.
If you delete, note the rank of the deleted row and update the row with rank of $max to the rank you just deleted.

Using PHP to show the latest X rows in an Oracle table

I'm having a problem getting Oracle to return the latest X rows in a table (i.e. in this case it would be returning our newest orders).
$stid = oci_parse($conn, "
SELECT OrderNo, InvoiceNo
FROM Orders
WHERE ROWNUM <= 5
ORDER BY ROWNUM DESC
");
Reading this makes sense in that the highest row numbers should be first and it should show the first five. What am I doing wrong here?
You just need to encapsulate your query in a subquery and you should be fine:
SELECT *
FROM
(
SELECT OrderNo, InvoiceNo
FROM Orders
ORDER BY OrderNo, InvoiceNo DESC -- choose the correct sorting here
)
WHERE ROWNUM <= 5

Mysql Query to fetch records

I have a table structure which looks like as follows
In the above table I need the team_id for which win+runs_scored is maximum.
I know that task can be accomplished by PHP code but if there is any query possible for this then it would be easier for me and also main thing is that in real table contains more then 15000 rows so please if some can can provide me a better solution then it would be great
select t.team_id
from YourTable t
order by t.win + t.run_scored desc
limit 1
SELECT teamid FROM
(
SELECT max(win+run_scored),teamid FROM YOUR_TABLE GROUP BY teamid
ORDER BY max(win+run_scored) desc
)
WHERE rownum <= 1
select max(t.win + t.run_scored) ,t.team_id
from YourTable t
group by t.team_id
Limit 1

Select on Mysql inverse order

i have a MySql table that consists of 2 basic things:
The id and a value.
To show that on my page, i need to select, for example, the last 100 rows on reversed order.
So imagine that someone is putting data on it:
Id, value
1, 10
2, 9
3, 21
4, 15
i need, to select the last "3" rows (LIMIT + ORDER Clause), but not like this: 4,3,2 but like this: 2,3,4.
I know how to do that on code, but maybe there is a simple solution for that on Mysql and i don`t know.
Thanks
My SQL Query is like this right now:
SELECT `Data`.`id`, `Data`.`log_id`, `Data`.`value`, `Data`.`created` FROM `control_panel`.`datas` AS `Data` WHERE `Data`.`id` > 1000 AND `Data`.`log_id` = (2) ORDER BY `Data`.`id` DESC LIMIT 100
You need to wrap the first ORDER BY in a subselect which will return a limited selection ordered in descending order, then you can order that result in the outer query in ascending order:
SELECT
a.*
FROM
(
SELECT id, value
FROM tbl
ORDER BY id DESC
LIMIT 3
) a
ORDER BY
a.id
One way to do this would be with a sub-select.
SELECT *
FROM (SELECT * FROM table_name ORDER BY id DESC LIMIT 3) tmp
ORDER BY id ASC
simply
SELECT t.*
(SELECT * FROM table_name
ORDER BY column_name DESC
LIMIT 0,3) t
ORDER BY t.column_name ASC
use DESC to descending order, ASC to increasing order

Categories