A different logic in ranking - php

I have to find a solution for my ranking scenario.
Say i have 100 users in database. And there is 5 subject in another table. In my project users have an option to rate 1 to 5 rating of any subjects. Means a user should have 5 different rating for 5 different subject. I need to shoe on the front page which is the most rated subject on the landing page.
I have a plan like create a table like
table name: user_subject_rate
Structure
id: user_id: subject1: subject2: subject3: subject4: subject5
1 1 3 1 2 5 4
When i create a table like this what happens if a new subject come to rate?
Can anybody suggest me a solution for this? I am using mysql as database.

I would advise you to structure your tables like below.
users
user_id | name
-----------------
1 Michael
2 Andrew
3 Annie
subjects
subject_id | name
----------------------
1 Maths
2 English
3 Physics
4 Chemistry
5 Biology
users_subjects_scores
user_id | subject_id | score
----------------------------
1 1 5
1 2 5
1 3 4
1 4 2
1 5 3
2 1 1
2 2 2
2 3 4
2 4 5
2 5 3
Then you can work out the total score of each subject using this query:
SELECT
name,
COALESCE(SUM(score), 0) AS total_score
FROM
subjects
LEFT JOIN
users_subjects_scores USING (subject_id)
GROUP BY
subject_id
ORDER BY
SUM(score) DESC
Then adding a new subject is as simple as adding a new row to the subjects table.
You can see an SQL fiddle here.

Related

how to get the records from the user table on the basis of the decreasing number of matching records using active record codeigniter

i am having two tables one is the user answers in which users answers some questions about himself
user_id question_id answer_id
1 2 3
1 4 2
1 2 1
1 2 3
1 4 1
2 2 3
2 4 2
2 2 1
2 2 3
2 4 1
the other one is the prefernce table in which the user answers about his partner
user_id question_id answer_id
1 2 3
1 4 2
1 2 1
what i need to do is first i have to take question_id and answer_id for a particular user from the second table and match the question_id and answer_id
to the first table and we need to fetch the user detail from the third table on the basis of decreasing number of answer matched for that user to the other.

Auto complete search from multiple tables

Eg:
**Category Table**
Catg_id Catg_name
-------------------
1 Bike
2 Car
**Company Table**
Company_id Company_name
--------------------------
1 Bajaj
2 Honda
**Company_category table**
com_catg_id Company_id Category_id
---------------------------------------
1 1 1
2 2 1
3 2 2
** Models table**
Model_id Model_name com_catg_id
----------------------------------------
1 Pulsar 220 1
2 Unicorn 2
3 City 3
**Purchase Table***
Purchase_id Vehicle_No Rate model_id status
-------------------------------------------------------
1 KL 02 AN8306 50000 2 0
2 KL 10 AZ4764 120000 1 1
3 KL 04 AV8578 800000 3 1
These are 4 Database tables using.
I am using ajax for auto complete searching through a single field
eg: searching car, want to list all cars in purchase table of status 1
if searching bike, want to list all bike in purchase table of status 1
search using company name, want to list all vehicle from that company in purchase table of status 1
same as search using model name, vehicle no,rate want to list matched items in purchase table
Please help me and please send a mysql query for implementing this.
Check this tut
This would surely help you.
This tutorial is for single field. It isn't hard to modify the code and use for multiple fields

Facted Search using php and mysql

I'm trying to implementing faceted search in a Jewellery store, but failed. Problem is when try to filter the attributes table. structure is as follows:
Products Table:
Id Product_Code Product_Name
1 ABCGOLD1GM 1 gm Gold
2 ABCGOLD2GM 2 gm Gold
3 ABCGOLD394 3.94 gm Gold
Attributes Table:
Id Attr_Name Alias
1 Metal metal
2 Fineness fineness
3 Weight weight
Product_Attributes Table:
id product_id attr_id value
1 1 2 9999
2 1 3 1 gm
3 2 2 9999
4 2 3 2 gm
5 3 3 3.94 gm
6 3 2 9167
Now i want to filter if someone selects 1 gm with 999 and 3.94 gm. If you know faceted search then you can easily know what i mean. I want to make query to do the same with the table structure above.

MySQL: GROUP BY within ranges

I have a table with scores like this:
score | user
-------------------
2 | Mark
4 | Alex
3 | John
2 | Elliot
10 | Joe
5 | Dude
The table is gigantic in reality and the real scores goes from 1 to 25.
I need this:
range | counts
-------------------
1-2 | 2
3-4 | 2
5-6 | 1
7-8 | 0
9-10 | 1
I've found some MySQL solutions but they seemed to be pretty complex some of them even suggested UNION but performance is very important. As mentioned, the table is huge.
So I thought why don't you simply have a query like this:
SELECT COUNT(*) as counts FROM score_table GROUP BY score
I get this:
score | counts
-------------------
1 | 0
2 | 2
3 | 1
4 | 1
5 | 1
6 | 0
7 | 0
8 | 0
9 | 0
10 | 1
And then with PHP, sum the count of scores of the specific ranges?
Is this even worse for performance or is there a simple solution that I am missing?
Or you could probaly even make a JavaScript solution...
Your solution:
SELECT score, COUNT(*) as counts
FROM score_table
GROUP BY score
ORDER BY score;
However, this will not returns values of 0 for count. Assuming you have examples for all scores, then the full list of scores is not an issue. You just won't get counts of zero.
You can do what you want with something like:
select (case when score between 1 and 2 then '1-2'
when score between 3 and 4 then '3-4'
. . .
end) as scorerange, count(*) as count
from score_table
group by scorerange
order by min(score);
There is no reason to do additional processing in php. This type of query is quite typical for SQL.
EDIT:
According to the MySQL documentation, you can use a column alias in the group by. Here is the exact quote:
An alias can be used in a query select list to give a column a
different name. You can use the alias in GROUP BY, ORDER BY, or HAVING
clauses to refer to the column:
SELECT
SUM(
CASE
WHEN score between 1 and 2
THEN ...
Honestly, I can't tell you if this is faster than passing "SELECT COUNT(*) as counts FROM score_table GROUP BY score" into PHP and letting PHP handle it...but it add a level of flexibility to your setup. Create a three column table as 'group_ID', 'score','range'. insert values into it to get your groupings right
1,1,1-2
1,2,1-2
1,3,3-4
1,4,3-4
etc...
Join to it on score, group by range. THe addition of the 'group_ID' allows you to set groups...maybe have group 1 break it into groups of two, and let a group_ID = 2 be a 5 set range (or whatever you might want).
I find the table use like this is decently fast, requires little code changing, and can readily be added to if you require additional groupings or if the groupings change (if you do the groupings in code, the entire case section needs to be redone to change the groupings slightly).
How about this:
select concat((score + (1 * (score mod 2)))-1,'-',(score + (1 * (score mod 2)))) as score, count(*) from TBL1 group by (score + (1 * (score mod 2)))
You can see it working in this fiddle: http://sqlfiddle.com/#!2/215839/6
For the input
score | user
-------------------
2 | Mark
4 | Alex
3 | John
2 | Elliot
10 | Joe
5 | Dude
It generates this:
range | counts
-------------------
1-2 | 2
3-4 | 2
5-6 | 1
9-10 | 1
If you want a simple solution which is very powerful, add an extra field within your table and put a value in it for the score so 1 and 2 have the value 1, 3 and 4 has 2. With that you can group by that value. Only by inserting the score you've to add an extra field. So your table looks like this:
score | user | range
--------------------------
2 | Mark | 1
4 | Alex | 2
3 | John | 2
2 | Elliot | 1
10 | Joe | 5
5 | Dude | 3
Now you can do:
select count(score),range from table group by range;
This is always faster if you've an application where selecting has prior.
By inserting do this:
$scoreRange = 2;
$range = ceil($score/$scoreRange);

Connecting 3 tables to get data [duplicate]

This question already has answers here:
What's the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL JOIN? [duplicate]
(3 answers)
Closed 8 years ago.
I have 3 tables - User table, book1 table, book2 table.
User table is like this -
user_id | gender | l_name | f_name
-------- -------- -------- -------
1 male Doe Jon
2 female Xu Jini
3 female Din Jane
book1 table -
b_id | user_id | amount | date
----- --------- -------- ----------
1 3 98.30 2014-05-14
2 1 65.70 2014-05-07
3 2 14.40 2014-05-06
4 2 55.60 2014-05-07
book2 table -
b_id | user_id | amount | date
----- --------- -------- ----------
1 2 38.20 2014-04-06
2 3 84.40 2014-04-02
3 3 31.30 2014-04-12
4 1 74.40 2014-05-06
The user gives a date range as input and I want to calculate the sales count(COUNT), total amount(SUM) and the max date(MAX) for that date range. After this I want to connect this data to the user table and get the gender and name using the user_id.
I wrote this query to get the data for the given date range from book1 and book2 tables-
SELECT * FROM book1
WHERE date between '2014-04-02' and '2014-05-15'
UNION ALL
SELECT * FROM book2
WHERE date between '2014-04-02' and '2014-05-15'
ORDER BY customer_id;
By this i get all the rows in the book1 and book2 table which satisfy the date range. Now should i use subquery or something else to reach the goal. I think sql should take care till getting the count, sum and max from book tables. Then the connection to the user table should be done in PHP. Am i on the right path? Can everything be done in SQL? I am kinda lost.
Yes, you can do it in SQL using a plain JOIN.
This will basically get all users and join them up with their respective amounts in the period. After that, the results are grouped by user so that we can sum up the amounts.
SELECT u.user_id, u.l_name, u.f_name, SUM(x.amount) `total amount`
FROM user u
JOIN (
SELECT user_id, date, amount FROM book1
UNION ALL
SELECT user_id, date, amount FROM book2
) x
ON u.user_id = x.user_id
AND x.date between '2014-04-02' and '2014-05-15'
GROUP BY u.l_name, u.f_name,u.user_id
An SQLfiddle to test with.
As a side note, learning about joins is really a necessity to work efficiently with SQL databases.

Categories