I've got a database table called servers with three columns 'id', 'name', and 'votes'.
How can I select the position of column id 5 by votes?
Example, I want to check which position server 3 is in by votes in my competition?
If I've interpreted your question correctly, you are asking how to find the rank of the row with id 5 in a list of servers sorted by votes. There is a complex solution, which requires sorting, but the easier solution which can be done in O(log(n)) space and O(n) time is to simply measure the number of votes for id = 5
select votes from servers where id = 5;
and then walk through the database and add one for every server encountered that has smaller number of votes. Alternatively, you can do something like:
select count(*) from servers where votes <= %votes
It is excessive to sort this (O(nlog(n) time) when you can simple iterate through the entire list once and gather all the information you need.
Use LIMIT:
SELECT id, name, votes FROM servers ORDER BY votes DESC LIMIT 2,1;
LIMIT a, b means "give me b rows, starting at row a", and a is zero-based.
OK, I misunderstood. Now. Suppose your server has 27 votes.
SELECT COUNT(*) FROM servers WHERE votes < 27;
Your server's rank will be 1 plus the result; ties are possible (i.e. ranks will be like 1, 2, 3, 3, 3, 6, 7, 7, 9 etc.).
Related
I'm trying to fix my problem on using AVG, I found some similar/relevant solutions and have attempted to apply it on my query however I still couldn't get the correct solution.
Here's my query:
SELECT unt_id, sum(enteredCode) / count(DISTINCT unt_id) AS 'avg' FROM tbl_code GROUP BY unt_id
Where enteredCode has the value of 1 and unt_id could be Chemistry, Physics, etc.
I think I'm missing something as it only shows the sum not the average.
You should just use the AVG function:
Select unt_id, avg(enteredCode) from tbl_code group by unt_id
Try thinking of GROUP BY as taking a big pile of rows and putting them into smaller piles, where each smaller pile is identified with a unique value among all groups.
In your query:
SELECT unt_id
, sum(enteredCode) / count(DISTINCT unt_id) AS 'avg'
FROM tbl_code
GROUP BY unt_id
you have asked to have all the rows grouped by unt_id and if unt_id has 6 distinct values like 1, 3, 9, 12, 18, 24 (across however many rows there are in the table), you'll have 6 groups where the first group consists of all rows where unt_id = 1, the second group where all rows have unt_id = 2, and so on.
Now what? Group functions like SUM(), COUNT(), AVG(), MAX(), MIN() will look at the individual groups of rows and give you one result per group.
Going back to your query, asking for COUNT(DISTINCT unt_id) for, say, the group where unt_id = 3, you're just going to get 1; the database put all rows where unt_id = 3 in that one group so there's only one distinct unt_id value. Same goes for groups 1, 9, 12, 18, and 24; they only have one distinct unt_id in their groups as well. (As an aside, note that using this grouping, MAX(unt_id) = MIN(unt_id) = unt_id for each group.)
If you just consider:
SELECT unt_id
, count(DISTINCT unt_id) as dist_count
FROM tbl_code
GROUP BY unt_id
you'll get one row returned for each unique unt_id value in your data, and the dist_count will be 1 for each of them. Using this count in your own average calculation (SUM(enteredCode) / COUNT(DISTINCT unt_id)) you're basically just doing SUM(enteredCode) / 1 so you're only seeing the sum.
When you said "enteredCode has the value of 1" it sounds like 1 is the only value and if that was the case, the average isn't going to be all that exciting - it'll just be 1, too. Assuming enteredCode has other values, as #bitfiddler said, you can just used the AVG function and call it done, assuming that you're looking to find the average enteredCode for all of the rows in each unt_id group. (If you wanted to use the explicit SUM / COUNT calculation for the average, just remember that AVG() = SUM() / COUNT() and rows where is null will not be considered.)
Hopefully this provides some insight as to why you're not getting the result you were intending.
I'm looking for a mysql select that will allow me to select (LIMIT 8) records after some changing number of first few matches;
select id
from customers
where name LIKE "John%"
Limit 8
So if i have a table with 1000 of johns with various last names
I want to be able to select records 500-508
You can send the offset to the limit statement, like this:
SELECT id
FROM customers
WHERE name LIKE "John%"
LIMIT 8 OFFSET 500
Notice the OFFSET 500 on the limit. That sets the 'start point' past the first 500 entries (at entry #501).
Therefor, entries #501, #502, #503, #504, #505, #506, #507 and #508 will be selected.
This can also be written:
LIMIT 500, 8
Personally, I don't like that as much and don't understand the order.
Pedantic point: 500-508 is 9 entries, so I had to adjust.
As a solution please try executing the following sql query
select id from customers where name LIKE "John%" Limit 500,8
I have a table with two columns of importance, customer ID# and timestamp. Whenever a customer orders something, five rows are created with the customer ID # and the timestamp of when it went through.
If there is more than five rows, it means our system hasn't processed the order correctly and there could be a problem, and I was asked to look through the log to find the customer IDs of any people who received more than 5, as well as how many times they received an incorrect amount and the number they received each time (when it was not 5)
I want it to show me, whenever the same customer ID (in column "ID") has more than 5 rows with the same timestamp (column "stamp") it will tell me 1. the person's customer ID 2. how many times this irregularity has happened to that customer ID, and 3. how many rows were in each irregularity (was it 6 or 7... or more? etc.) (if #2 was 3 times, I would like #3 to be an array like { 7, 8, 6 })
I don't know if this is possible... but any help at all will be appreciated. Thanks!
This should get you most of the way there:
SELECT `CustomerID`, `Timestamp`, COUNT(1)
FROM
OrderItems
GROUP BY
`CustomerID`, `Timestamp`
HAVING
COUNT(1) > 5
This will get you the IDs and Timestamps with more than 5 rows. I am making the assumption that the timestamps for all 5 (or more rows) are identical.
SELECT A.ID, A.TIMESTAMP
FROM "TABLE" A
WHERE
(SELECT COUNT(B.ID)
FROM "TABLE" B
WHERE B.ID = A.ID
AND B.TIMESTAMP = A.TIMESTAMP) > 5
I have this table,
person_id int(10) pk
points int(6) index
other columns not very important
I have this random function which is very fast on a table with 10M rows:
SELECT person_id
FROM persons AS r1 JOIN
(SELECT (RAND() *
(SELECT MAX(person_id)
FROM persons)) AS id)
AS r2
WHERE r1.person_id >= r2.id
ORDER BY r1.person_id ASC
LIMIT 1
This is all great but now I wish to show only people with points > 0. Example table:
PERSON_ID POINTS
1 4
2 6
3 0
4 3
When I append AND points > 0 to the where clause, person_id 3 can't be selected, so a gap is created and when the random select person_id 3, person_id 4 will be selected. This gives person 4 a bigger chance to be chosen. Any one got suggestions how I can adjust the query to make it work with the where clause and give all rows same % of chance to be selected.
Info table: The table is uniform, no gaps in person_id's. About 90% will have 0 points. I want to make the query for where points = 0 and points > 0.
Before someone will say, use rand(): this is not solution for tables with more than a few 100k rows.
Bonus question: will it be possible to select x random rows in 1 query, so I do not have to call this query a few times when i want more random rows?
Important note: performance is key, with 10M+ rows the query may not take much longer than the current query, which takes 0.0005 seconds, I prefer to stay under 0.05 second.
Last note: If you think the query will never be this fast with above requirements, but another solution is possible (like fetching 100 rows and showing x random which has more than 0 points), please tell :)
Really appreciate your help and all help is welcome :)
You could generate in-line gap-free id's for the records that you really want to work with, and generate then the random selector using the total number of records available.
Try with this (props to the chosen answer here for the row_number generator):
SELECT r1.*
FROM
(SELECT person_id,
#curRow := #curRow + 1 AS row_number
FROM persons as p,
(SELECT #curRow := 0) r0
WHERE points>0) r1
, (SELECT COUNT(1) * RAND() id
FROM persons
WHERE points>0) r2
WHERE r1.person_id>=r2.id
ORDER BY r1.person_id ASC
LIMIT 1;
You can mess with it in this sqlfiddle.
I have a sql statement that brings back ids. Currently I am ordering the id's with the usual "ORDER BY id". What I need to be able to do is have the query order the first 3 rows by specific id's that I set. The order the remaining as it is currently. For example, I want to say the first 3 rows will be id's 7,10,3 in that order, then the rest of the rows will be ordered by the id as usual.
right now i just have a basic sql statement...
SELECT * from cards ORDER BY card_id
SELECT *
FROM cards
ORDER BY
CASE card_id WHEN 7 THEN 1 WHEN 10 THEN 2 WHEN 3 THEN 3 ELSE 4 END,
card_id
A bit shorter than Quassnoi's query, with FIELD :
-- ...
ORDER BY FIELD(card_id, 3, 10, 7) DESC
You have to invert the order because of the DESC, I didn't find a way to do it more naturally.