简体   繁体   中英

SQL- insert row into table based on value, then determine position in table

I have a website which records hours played of a certain videogame. The table currently holds the name and hours played of 20k players. If a new user enters their information, how could I determine their position in the table?

Ideally a method which is as easy as possible on the CPU so it can deal with bursts of traffic, and even if the table grows (I assume ORDER BY is not advised for very large table!?)

For example, current table:

User // Hours played
Bob // 54
Dave // 584
Steven // 63

New user is Andy, hours played 300. I simply want to get returned the value '2' as he is the second on the table, ordered by hours played descending.

Thanks in advance!

Your syntax will vary depending on the database server you use (MySQL versus Oracle versus Microsoft SQL Server), but all modern RDBMS's support indexes in some fashion. By constructing the appropriate index (and then tuning on appropriate hardware), an ORDER BY clause or windowing function is perfectly acceptable even on large tables.

You could achieve this by using the 'RANK' function:.

Here's a quick example of how it could work using Microsoft SQL Server:

--Create an example of your table
CREATE TABLE #HoursPlayed
(
    vchName VARCHAR(255),
intHoursPlayed INT
)

--Add in the initial daa
INSERT #HoursPlayed VALUES ('Bob', 54), ('Dave', 584), ('Steven', 63)

--Now add in Andy
INSERT #HoursPlayed VALUES ('Andy', 300)

--Now see where Andy fits in the list ordered by hours played
SELECT RANK()OVER(ORDER BY hp.intHoursPlayed desc) Position, *
FROM #HoursPlayed hp

Andy will be returned as position '2' from the SELECT statement as he has the second highest number of hours played in the list of players.

The above syntax can easily be altered to return a single row and the position of the player in the overall list.

To appease the user questioning the solution, here's the final query that you can use. It will allow you to specify a single user and get there position in terms of hours played

SELECT *
FROM 
(
   SELECT RANK()OVER(ORDER BY intHoursPlayed desc) Position, *
   FROM #HoursPlayed
) hp
WHERE hp.vchName = 'Andy'

Note that using a subquery can be detrimental on large datasets.

select count(1) + 1 as Place
from Players
where HoursPlayed > (select HoursPlayed from Players where UserName = @UserName)

if I understood you right, you have a simple table like this:

Table(USRNAME, HOURS_PLAYED)

..and information in that table is as such:

"Bob", 54
"Dave", 584
"Steven", 63

There is basically nothing wrong with this layout but if you want to retrieve the "position" from the database, you really should add another column with an unique value. This kind of columns are called primary keys . Why should you use this? Because relational databases work best if you treat them like bags of marbles. You tell the database which data you want and the database engine finds it for you. They are based on set theory . So your new table should look something like this:

Table(ID, USRNAME, HOURS_PLAYED)
1, "Bob", 54
2, "Dave", 584
3, "Steven", 63

This would be the "correct" way of doing it or as it is usually phrased: the best-practice.

THAT SAID, there is a way, but I strongly advise against using it. MS SQL and also other database engines incoroporate a concept of ROW_NUMBER(). When you SELECT data from table, the server retrieves it in a 2D table. SQL engine is able to calculate the index (not necessarily the actual position in the table!!!) if the returned row. Please refer to this link: http://msdn.microsoft.com/en-us/library/ms186734.aspx .

So imagine a query like this:

SELECT USRNAME, HOURS_PLAYED FROM Table WHERE USRNAME='Bob';

This query would return the correct record, but you dont know the position. If you use an ID column, it would be simple.

SELECT ID, USRNAME, HOURS_PLAYED FROM Table WHERE USRNAME='Bob'; 

This query would return number 1.

But please keep in mind that database engine doesn't care the position of the record. So there is no difference between ID=3 and ID=23454 for the database itself. Just a number without a semantic meaning.

I suggest you read up on the database design basics and you will be able to solve the rest of your db-related problems fairly quickly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM