views:

323

answers:

5

Hello,

I have a file hosting site where I provide a point for every unique download to user.

Sample of my table
Sample table

These points can be redeemed by user. So for example if a user redeems 100 points than what is the best query to reduce points available from each row till 100 points are reduced.

Thank You.

A: 

Just add a column in your user table with the amount of redeemed points. Is that a viable solution for you?

Emil Vikström
No, Best would be reduce because whole application is ready and it relies on this table structure and if its change means everything corresponding would have to be changed.
Shishant
Then read Jordans comment :-)
Emil Vikström
if the whole application is ready, why are you still coding? ;-)
Natrium
Sorry what I mean is everything else is ready this is the last part I am working on.
Shishant
+3  A: 

You should create two tables for this:

Table files
- id
- name
- size

Table points
- id
- file_id
(- user)
- points

Insert a new file:

INSERT INTO files (name, size) VALUES ('kat92a.jpg', 105544); // New file with ID 1

Now you can give points to a file, negative or positive:

INSERT INTO points (file_id, points) VALUES (1, 100); //Positive points
INSERT INTO points (file_id, points) VALUES (1, -10); //Negative points

And you can select the total number of points:

SELECT 
    files.name, 
    files.size, 
    (SELECT sum(points) FROM points WHERE file_id = 1) AS points 
FROM files
WHERE id = 1 
Harmen
Quite good logic
Shishant
+1  A: 

Alright, then, here's the SQL-dumb way I would do it. Hopefully an SQL guru will come around with a better solution. Note: This is pure pseudocode; write your own code based on this--it's not going to work out of the box.

$total_to_deduct = 100;

// Each time, get the row with the highest points
$top_points_query = "SELECT id, points FROM my_table ORDER BY points DESC LIMIT 1;"

do {
  $result = do_query($top_points_query);

  if($result) {
    // I'm assuming you don't want to deduct more points from a row than it has
    $num_to_deduct = min($result['points'], $total_to_deduct);

    // Now deduct the points from the row we got earlier
    $update_query = "UPDATE my_table SET points = points - $num_to_deduct
                     WHERE id = $result['id']";

    if(do_query($update_query)) {
      $total_to_deduct -= $num_to_deduct;
    }
  }
} while($total_to_deduct > 0); // If we still have points to deduct, do it again
Jordan
A: 

Here is a pure SQL solution, but I warn you that (a) this is untested and (b) it's just a concept.

DECLARE curs CURSOR FOR
    SELECT
        id,
        points,
    FROM
        points
    WHERE
        points > 0;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET remPoints = 0;
OPEN curs;

SET remPoints = 100; /* modify this value, probably in your app */

REPEAT
    FETCH curs INTO cId, cPoints;

    IF remPoints >= cPoints THEN
        UPDATE points SET points = 0 WHERE id = cId;
    ELSE
        UPDATE points SET points = points - remPoints WHERE id = cId;
    END IF;
    SET remPoints = remPoints - cPoints;
UNTIL remPoints <= 0;

CLOSE curs;
Dereleased
+1  A: 

Seems like you just need a simple update Statement and allows you to update the row and if it's more than 100 not update it.

update table set points = if( (points+<VALUE>) <= 100,points+<VALUE>,points) where id = <FILE ID>  

This will check to see if the points is higher than 100, if it is then the update statement will just return no results. If the value is less than 100, then it will update the table and give you back the amount of rows that were updated.

RaginBajin
I didnt knew this kind of statements can be written for sql, can you tell me what should be inserted in <VALUE>
Shishant
Value is the amount of points that you are going to be assigning that column. So, if the user downloading the file is going to use 15 points, then VALUE should be 15.
RaginBajin
Sorry this is not what I wanted, I want to deduct points from rows till 100 points are deducted. So if a single row has more than 100 points deduct it or else keep on deducting till 100 points are deducted.
Shishant
Then remove the where clause. The where clause is pointing the query to one specific row. If you want update every row remove that piece, and it will update every row with the amount of points to subtract. If you want to keep updating each row by only 1 point, then put it in a loop in your code till every row in that table returns back no results.
RaginBajin