3 Conditions + Random Order + Pagination (Code Igniter + MySQL) - php

I have a tricky issue to solve, let me see if you can help me...
Im developing a services directory using CodeIgniter + MySQL and, due to my client's business rules, theres 3 plan types. (Platinum, Gold and Silver - in this order from best to worse)
There is a table with the companies tha advertise in the directory, and each one of them may be paying one of this 3 plans.
The problem is:
I have to present the results following this rules:
1. Platinum comes first, than gold, than silver
2. Each range of results MUST BE random itself
Platinum 2
Platinum 1
Platinum 3
Gold 3
Gold 1
GOld 2
Silver 2
Silver 3
Silver 1
refresh and i get:
Platinum 1
Platinum 3
Platinum 2
Gold 2
Gold 1
GOld 3
Silver 2
Silver 1
Silver 3
The query in php is something like this:
// after a Select and several joins to filter city, provinces, service types
// i do this to randomize , order and group
$query = $this->db->order_by('plan.level', 'desc');
$query = $this->db->order_by('busines.id', 'random');
$query = $this->db->group_by('business.id');
return $query->result_array();
Until now, so far so good.
The problem is, with so many results, i have to paginate them :)
How can i do this keeping in mind that:
The plan priority must be the same through the pages
the results must be random within the plan "blocks"
BUT the pagination CANT repeat records through pages or omiss some results
i have to achieve something like this (e.g. with a 4 per page pagination)
Page I:
Platinum 1
Platinum 4
Platinum 5
Platinum 3
Page II:
Platinum 2
Gold 5
Gold 3
Gold 1
Page III:
Gold 4
Gold 2
Silver 2
Silver 5
Page IV:
Silver 1
Silver 3
Silver 4
and refreshing, randomly changing the position of records INSIDE THE PLAN BLOCKS, within the pages, without repeat or omiss results in the 4 pages, in this example.
Somebody can help me, please.
Its a challenge one ;) Thanks, Adriano.

Since the randomization of results has to be preserved across sessions (for pagination), why don't you store in PHP instead of MySQL?
An initial query to get the randomized queries in MySQL:
$this->db->select('id');
// The rest of your ActiveRecord query here, randomized
And perhaps storing the IDs in PHP:
$this->session->set_userdata('random_query', $array_of_random_ids);
Then querying it per page
$array_of_random_ids = $this->session->userdata('random_query');
$this->db->from('business');
$this->db->where_in('id', array_slice($array_of_random_ids, $page_number * $length, $views_per_page);
$this->db->limit($views_per_page, $page_number * $length);
And of course resetting the session later, if that's how you choose to do it.

Related

Badge System with Variant Criteria, DB Design

Working on the DB design of a Badge System which will work synchronously(request/response) for variant criteria for more than 1000+ badges I am wondering how the badges will be checked when a user does a request.
A first DB Schema I am thinking is:
Badge
id name
1 Check-in 10 Beers, of X Manufacturer the last 30 days
2 Check-in 5 Organic Beers from England
3 Comment on 5 different check-ins
Rules
id key
1 count_of
2 manufacturer_of
3 last_x_days
4 comment_x_diff_checkins
5 from_country_x
BadgeRules
badge_id rule_id value
1 1 10 (check-in 10 beers)
1 2 122 (manufacturer_id)
1 3 30 (days)
The think is that the User makes a check-in and the system should check the different variants for different badges.
As an example need to check on the above DB data that the User made 10 check-ins of Manufacturer with ID 122 the last 30 days. Obviously makes no sense to check 1000+ badges for each request but somehow can be checked only the Badges that the User can win for that check-in.
I was thinking to save for user's state in a different db table but I dont think that this can work for all the rules like last_x_days
UserState
id user_id key value
1 1 checkins 8
2 1 comments 12
P.S. I have seen the Untappd app which has thousands of Badges and it assign them on users request.
I would be grateful for a proposal.

Calculate commision based on level completeness of a binary tree

I have 2 tables.
Business Plans
Users Binary
Right now, if you see users_binary, The following hierarchy is being developed.
1
/ \
3 4
/ \ / \
19 33 18 32
I want to calculate commission based of completeness of level. I has 2 childs. Its first level is complete. Now User 1 is on PLAN 1. Plan 1's right and left points are 20 and commission percentage is 4.5. It's first level is complete. It will get ((20+20)*4.5%) commission. When 3 and 4 also completes their 1st levels, user 1 will get ((20+20+20+20)*4.5%) commission. Just 1 thing to note. In query, we will note that the commission being calculated is from this Monday to Saturday and point_status should be equal to N.
This is my getBasicTree function.
function getBasicTree($user_id)
{
$query="select user_id,first_name,last_name,leg from users
where introducer_id = '".$user_id."'
and leg != ''";
if(($data=$this->CustomQuery($query))!=null)
{
return $data;
}
return 0;
}
Anyone willing to help me out understanding the logic how it will be done. I am unable to understand recursion and make a logic for it.

Mysql return only items that have n number of property matches

I have a database of items and each item has various number of properties. Is it possible for MySql only to return items that have a certain number of matches (not properties) when a search is run?
Example: I am searching for any item with a wheel that is red and has a tire.
This would return all items with these three matches even if they have more properties and would automatically exclude anything that has less than 3 matches.
I have tried playing with the COUNT + GROUP BY + HAVING but I was unable to put together a meaningful working code. Before I spend more time on this I would like to know if it is possible at all.
TABLE DESIGN
ID ITEM PROPERTY
1 1 red
2 1 wheel
3 1 tire
4 2 red
5 2 wheel
6 2 tire
7 2 lamp
8 3 red
9 3 wheel
10 4 red
I would like it to return ITEM 1 and 2
You would do this with a group by and having. You really provide no information about your data structure, but the basic idea is:
select ip.item
from design ip
where ip.property in ('wheel', 'red', 'tire')
group by ip.item
having count(distinct ip.property) = 3;

How to store more than one virtual currency in SQL

I have a table called users which currently contains column money of type integer which contains the amount of money the user currently has.
However, I would like to expand and have a couple of more currencies that are based on each other. 1 Gold = 10 Silver = 100 Bronze (or something like that). When you get 100 Bronze, they will convert into 1 Gold. The same with 10 Bronze = 1 Silver. All these currencies have their own column in my table. I have a hook function that is called on every request and updates the money, if possible.
I was told though I could use just one column money and then I can play with variables and take out the different currencies.
But my question is: What would be the best method?
In case the latter method is best: How do I put variables to an already existing object (an object which contains user data; I think it’s called stdClass or something like that)? $user->username, etc.?
Just store the equivalent number of bronze. Then use the following algorithm to get as much as possible converted to gold, from the remainder as much as possible to silver and the rest stays in bronze:
Set the number of gold to zero, silver to zero and bronze to whatever the database says.
Set the number of silver equal to the number of bronze divided by 10 (use integer division). Set the number of bronze equal to the number of bronze mod 10.
Set the number of gold equal to the number of silver divided by 10 (use integer division). Set the number of silver equal to the number of silver mod 10.
So if you have 9,327 bronze:
gold=0, silver=0, bronze=9,327
gold=0, silver=932, bronze=7
gold=93, silver=2, bronze=7
I've done something similar before, and I agree that you should just have the one column for "money", and compute other currencies as-needed. If you had separate columns, you'd have to rely on a trigger or application logic to keep them in-sync.
I would convert everything to bronze and just store that value. Any sort of transactions would also be converted to bronze first. The only time you need to convert to silver or gold would be for display.
One way is to only store all currency in Bronze.
That way if you have 123 Bronze you can convert them
123 / 100 //Gold with integer division which should be 1
Remaining are 123 - NumGold * 100 ie 23
so you have
23 / 10 // Silver with integer division should be 2
Remaining are 23 - NumSilver * 10 ie 3 bronze coins.
This was the SQL knows only about Bronze coins and showing them as Gold , Silver is all in the application layer
The accepted answer doesn’t account for values over 9999 since it will add 10 more to silver and give a false output.
The best solution is this:
var bronze, silver, gold;
var myMoney = 32141; // number from database
bronze = myMoney % 10;
myMoney = (myMoney - bronze) / 10;
silver = myMoney % 10;
gold = (myMoney - silver) / 10;
Output:
gold = 321
silver = 4
bronze = 1

standard deviation and mode

I have a system that monitors the performance of students. It tabulates the number of students who gained a score of 1,1.25,1.5,....5 (this is our grading system). For example:
grading system number of students
1 12
1.25 10
1.5 15
1.75 15
2 20
2.25 1
2.5 5
2.75 6
3 8
5 0
From this example, I need my system to determine which is the mode and then print it. I also need to get the standard deviation.
I need this in PHP. Can anyone help me with this?
Your ideas, comments, and suggestions are appreciated.
Update:
Here's what I've done so far:
Finished the standard deviation...but there are still discrepancies i can't resolve...when i calculate the standard deviation manually..the answer is different from the output of my system.. >.<
While for the mode I used an array..this is my code:
$sample = array($one[$ctr],$two[$ctr],$three[$ctr],$four[$ctr],$five[$ctr],$six[$ctr],$seven[$ctr],$eight[$ctr],$nine[$ctr],$ten[$ctr],$fda[$ctr]);
rsort($sample);
$holder = $sample[0];
//$holder = $mode;
The sorting is successful and I can the highest number but I need to print the value of $holder to a table using fpdf.
Any ideas, why the value is not visible in the output?
Well, the mode is easy. Just find the grade (2) which has the highest number of students (20) and there you are.
If there's more than one, then it's multi-modal and you should probably allow for that.
For the standard deviation, the method can be found here. It's basically working out the mean of all those numbers (let's simplify this by using 1, 1, 2 and 7):
1 + 1 + 2 + 7 10
------------- = -- = 2.5
4 4
then calculating the square root of the variance of all those samples from that mean:
_____________________________________________
/ (1-2.5)^2 + (1-2.5)^2 + (2-2.5)^2 + (7-2.5)^2
/ ---------------------------------------------
\/ 4
__________________________
/ 2.25 + 2.25 + 0.25 + 20.25
= / --------------------------
\/ 4
= 2.5
If you're asking a beginner-level question like how best to do this in a specific language like PHP, you should investigate the use of arrays and loops.

Categories