Get rank within table for any number - mysql

I have a bidding system in place. The user enters how much he wants to bid, which then sends a request via ajax to a PHP script, which then gets what rank that bid would place under the existing bids, and then displays it back to the bidder. This allows him to increase his bid to get the rank he wants.
For example
+-----------+------------+
| bidder_id | bid_amount |
+-----------+------------+
| 1 | 20 |
| 2 | 20 |
| 3 | 30 |
| 5 | 40 |
| 6 | 10 |
+-----------+------------+
The user bids 15$, the query gets the rank as 5th.
How would this query look like? Is is possible to insert a fake row with the new user's bid and then order everything?

Something simple like this should do it;
SELECT COUNT(*)+1 rank
FROM bids
WHERE bid_amount > 15
An SQLfiddle to test with.

Related

Selecting row data and a scaler in SQL

I have a job table, where each job has some metrics like cost, time taken, etc. I'd like to select information for a set of jobs, like the requestor and job action, and in addition to that row data, select some high-level metrics (min cost, max cost, min time taken, etc.).
The data changes frequently, so I'd like to get this information in a single select. Is it possible to do this? I'm not sure if this is conceptually possible because the DB would have to return row-level data along with aggregate data.
Right now I can get all the details and calculate the min/max, something like this:
select requestor, action, cost, time_taken from job;
But then I have to write code to find the min/max and this query has to download all the cost/time data when I am really only interested in the min/max. I really want to do something like
select (min(cost), max(cost), min(time_taken), max(time_taken)), (requestor, action) from job;
And get the aggregate data first, and then the row level data. Is this possible? (On a real server this is on MySQL, but for dev I locally use sqlite so it'd be nice if it worked there too, but not required).
The table looks something like this:
+----+-----------+--------+------+------------+
| id | requestor | action | cost | time_taken |
+----+-----------+--------+------+------------+
| 1 | 31233 | sync | 8 | 423.3 |
+----+-----------+--------+------+------------+
| 2 | 11229 | read | 1 | 1.3 |
+----+-----------+--------+------+------------+
| 3 | 1434 | edit | 5 | 152.8 |
+----+-----------+--------+------+------------+
| 4 | 101781 | sync | 12 | 712.1 |
+----+-----------+--------+------+------------+
I'd like to get back the stats:
min/max cost: 1/12
min/max time_taken: 1.3/712.1
and all the requestors and actions:
+-----------+--------+
| requestor | action |
+-----------+--------+
| 31233 | sync |
+-----------+--------+
| 11229 | read |
+-----------+--------+
| 1434 | edit |
+-----------+--------+
| 101781 | sync |
+-----------+--------+
Do you just want aggregation?
select requestor, action, min(cost), max(cost), min(time_taken), max(time_taken),
from job
group by requestor, action;

count groupings of multiple columns

I have a table of tickets to multiple dates of shows shows. basically, it looks like this...
+----+---------------+--------------+-----------+
| ID | ticket_holder | ticket_buyer | show_date |
+----+---------------+--------------+-----------+
ticket_holder and ticket_buyer are both user ids
If I wanted to count the total number of tickets that one ticket holder has, I could group by that holder and count the rows, but I want more stats than that.
I want to know a user's total bought tickets, how many they hold and how many shows they've bought tickets for.
+------+---------+--------+-------+
| USER | HOLDING | BOUGHT | DATES |
+------+---------+--------+-------+
| 1 | 12 | 24 | 7 |
+------+---------+--------+-------+
| 2 | 3 | 4 | 2 |
+------+---------+--------+-------+
| 3 | 1 | 2 | 1 |
+------+---------+--------+-------+
is it possible to put all this in a query, or do i need to do php stuff to make it happen?
I would do it in multiple queries. You can't group by either ticket_holder or ticket_buyer like you want, in a single query. If you try GROUP BY ticket_holder, ticket_buyer then it will group by both columns, which is not what you want.
SELECT ticket_holder, COUNT(*) AS tickets_held
FROM `a table of tickets` GROUP BY ticket_holder;
SELECT ticket_buyer, COUNT(*) as tickets_bought
FROM `a table of tickets` GROUP BY ticket_buyer;
SELECT ticket_buyer, COUNT(DISTINCT show_date) AS shows_bought
FROM `a table of tickets` GROUP BY ticket_buyer;
Not every task has to be accomplished in a single query! It's part of the design of SQL that it should be used by some application language, and you're expected to handle formatting and display in the application.

Get clan with bigger kills/deaths coef

I got table:
id | nick | clanid | kills | deaths | map
1 | xdd | 2 | 123 | 23 | 'map_1'
2 | xd | 1 | 23 | 32 | 'map_1'
this table continuing with similar records. I need to get only 1 result, it's should be clanid and coef(kills/deaths), of course i need the clan with higher coef. This table got many records with players which have different clanids, kills, deaths and map.
The complete result i need: it's clanid with higher coef at current map.I tried SQL like that:
SELECT `clanid`, SUM(kills)/SUM(deaths) as 'coef'
FROM `test_user_stats`
WHERE `map`='map_1'
But that returs only 1 record with last clanid and his coef.
What i have to do next?(i obviously need to use LIMIT 1 and ORDER BY coef, but i got problems even without going so far).

MySQL Query isn't showing most recent username

I have a special problem with my statistics query. I want to get the most recent username, duration, and connection count of every client that connected to a server. This is the query:
SELECT name, SUM(duration) AS time, COUNT(auth) AS connections
FROM analytics
WHERE duration IS NOT NULL
GROUP BY auth
ORDER BY time DESC;
The problem is that they query isn't showing the most recent username. It takes the first entrance of the client (identified by auth) in the database even if the client changed their username already.
Is there a way to get the most recent username of the client in the query above without slowing it down a lot?
Example Table:
| id | auth | name | duration |
|----|------|------|----------|
| 1 | u123 | Fire | 50 |
| 2 | u555 | Dan | 20 |
| 3 | u123 | Ice | 30 |
What I get:
| name | time | connections |
|------|----------|-------------|
| Fire | 80 | 2 |
| Dan | 20 | 1 |
What I want
| name | time | connections |
|------|----------|-------------|
| Ice | 80 | 2 |
| Dan | 20 | 1 |
I assume that you want most recent auth order by ID coz there is no other data to get it.
SELECT A.name, B.time, B.connections
FROM analytics AS A
INNER JOIN
(
SELECT auth, MAX(ID) AS MAXID, SUM(duration) AS time, COUNT(auth) as connections
FROM analytics B
WHERE duration IS NOT NULL
GROUP BY auth
) AS B
ON A.auth = B.auth AND A.ID = B.MAXID
If you have a TimeStamp column for the recent registred user.
you can get it using the max()
select * from database where registered like (select max(registered) from database;
I wish it will help. Just analyze the idea.

Get highest value from multiple columns and associated name column

I've got a table with these columns:
id | player1_name | player1_score | player2_name | player2_score | player3_name | player3_score | player4_name | player4_score | player5_name | player5_score
Given a single row, how do I get the highest playerX_score and the corresponding playerX_name?
I've tried using GREATEST(), but I can't get the playerX_name.
As an aside, I think your table would be better designed as id | name | score | position | teamid, where position goes from 1 to 5 and teamid serves to group everyone in the same team together. It would make this sort of query much easier (greatest-score-per-team with associated rows).
However, here's one way to do what you want with your current table:
SELECT GREATEST(player1_score,player2_score,player3_score,
player4_score,player5_score) as score,
CASE GREATEST(...) -- repeat the above
WHEN player1_score then player1_name
WHEN player2_score then player2_name
WHEN player3_score then player3_name
WHEN player4_score then player4_name
WHEN player5_score then player5_name
END as name
FROM mytable
I think your table structure isn't right for what you're trying to do. You want the database to know that there's some relationship between player1_name and player1_score, but that's not encoded in the table. A change that would make this much easier would be to give each player their own record, and use what you're currently calling id (which I assume is the ID for a particular game) to indicate which players go together.
It would look like this:
game_id | player_num | player_name | score
1 | 1 | Octern | 100
1 | 2 | Boris | 400
1 | 3 | Jarlsberg | 300
1 | 4 | Pete | 40000
...
Then, to find the high scorer for a given game (in this case, game #1), you'd say:
select player_name from scores
WHERE game_id = 1
ORDER BY score desc
LIMIT 1