PHP & MySQL Update Database Problems - php

I'm trying to change my rating system which only used one table before but now I'm changing it to use multiple tables and I really dont no how to
update or insert a new rating into the database and was wondering how to do this using my MySQL tables structure?
Also how do I do this by adapting the new code to my current PHP code which I want to change which is listed below.
First let me explain what my tables do they hold the information when students rate there own teachers I listed what the tables will hold in the
examples below to give you a better understanding of what I'm trying to do. Students are only allowed to rate there teachers once.
I provided the two MySQL tables that should be updated which are listed below.
My MySQL tables
CREATE TABLE teachers_grades (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
grade_id INT UNSIGNED NOT NULL,
teachers_id INT UNSIGNED NOT NULL,
student_id INT UNSIGNED NOT NULL,
date_created DATETIME NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE grades (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
letter_grade VARCHAR(2) NOT NULL,
grade_points FLOAT UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (id)
);
What the database will hold.
teachers_grades
id grade_id teachers_id student_id date_created
1 3 2 32 2010-01-23 04:24:51
2 1 32 3 2010-01-23 12:13:58
3 2 32 103 2010-01-23 12:24:45
grades
id letter_grade points
1 A+ 10
2 D 3
3 B 5
Here is the old PHP code.
// function to insert rating
function rate(){
$text = strip_tags($_GET['rating']);
$update = "update vote set counter = counter + 1, value = value + ".$_GET['rating']."";
$result = mysql_query($update);
if(mysql_affected_rows() == 0){
$insert = "insert into vote (counter,value) values ('1','".$_GET['rating']."')";
$result = mysql_query($insert);
}
}
Old table.
CREATE TABLE vote (
`counter` int(8) NOT NULL default '0',
`value` int(8) NOT NULL default '0'
);

first , do mysql_escape_string to the parametrs when inserting like :
mysql_real_escape_string($_GET['rating']);
second
you need to get all parameters (from GET or POST) and insert it to the db ,
the teacher_id ....
now i only see the rating.

Your old table was bit confusing as it seems like it only rates 1 teacher or teachers as a whole.
Now it seems like your new design process requires you to:
- store rating and averages of teachers
- track historical ratings from students
rating table should look something like
Table: rating
rating_id student_id teacher_id grade_id date_created
1 101 21 1 2010-01-23 04:24:51
2 102 21 1 2010-01-23 04:26:51
3 102 22 2 2010-01-23 04:28:51
4 103 24 1 2010-01-23 04:44:51
Your code usage:
$rating_value = $_GET['rating']; // Remember to sanitize your inputs
$student_id = $_GET['student_id'];
$teacher_id = $_GET['teacher_id'];
rate_a_teacher($teacher_id, $student_id, $rating_value);
Your method:
function rate_a_teacher($teacher_id, $student_id, $rating_value)
{
// Find the corrosponding to specified rating value
$grade_id = find_grade_id($rating_value); //TODO
$sql = "
INSERT INTO rating
('student_id', 'teacher_id', 'grade_id', 'date_created')
VALUE
($student_id, $teacher_id, $grade_id, NOW);
";
mysql_query($sql);
}
I skipped implementation for find_grade_id() for you to fill it in yourself.
The purpose of splitting your calcualted values to individual records is so that you can start do interesting reports,
like such:
Find average rating value of each teacher for the past 3 months:
SELECT teacher_id, (SUM(points)/COUNT(rating_id)) AS average_score
FROM rating
LEFT JOIN grades ON grades.id = rating.grade_id
WHERE date_created > SUBDATE(NOW(), INTERVAL 3 MONTH)
GROUP BY teacher_id

Related

Count the number of unique rows in SQL table using a single common column

I have the following table for an events website in an SQL database:
usereventsid event_id user_id reg_date rating comments attend
81 92 1 NULL NULL NULL 1
82 90 1 NULL NULL NULL 1
83 91 1 NULL NULL NULL 1
84 88 1 2017-03-21 NULL comment1 NULL
85 88 4 NULL NULL NULL 1
86 92 4 NULL NULL NULL 1
This table shows the id numbers of different events. If a user's id number appears in the table and has attend set to 1, they are attending the event. If a user's id number appears in the table but attend is null, they are not attending and have only commented on the event.
I want to be able to count the number of users that are attending each unique event. So in this case there are two users attending event 92 and 88, there is one user attending events 90 and 91. This is the information that I need to get from the table but I'm struggling to figure out how to do it.
At the moment here is my sql:
$eventsSql = "SELECT eventid, name, date, time, location, description
FROM Events
ORDER BY eventid";
$result = mysqli_query($conn, $eventsSql)
or die(mysqli_error($conn));
while($event = mysqli_fetch_assoc($result))
{
$id = $event['eventid'];
$name = $event['name'];
$date = $event['date'];
$time = $event['time'];
$location = $event['location'];
$des = $event['description'];
$sql = "SELECT event_id, attend
FROM User_Events
WHERE event_id = '$id' AND attend = '1'";
$attendanceResult = mysqli_query($conn, $eventsSql)
or die(mysqli_error($conn));
$num = mysqli_num_rows($attendanceResult);
echo "<!--echos html into the webpage-->";
In my head the second sql statement works as follows (I know this isn't correct because it's not producing the right result); the statement selects all of the rows that have the event id specified using the $id variable produced above and that also have attend set to 1. The number of these rows is then counted and the value placed in $num. What is actually happening is the statement is selecting every row in the table and $num is being set to 6. I don't understand why this is happening as $id should only match with one row in the case of values 90 and 91 and two rows with values 88 and 92.
Can someone help me figure this out please, thank you.
seems you need then number of distinct user attending an event
SELECT eventid, count(distinct user_id)
from Events
where attend =1
GROUP BY eventid
You can do this with one SQL statement using the GROUP BY clause and a sub query
SELECT SUM(user_count) FROM
(SELECT COUNT(user_id) AS user_count
FROM User_Events
WHERE attend=1
GROUP BY event_id ) AS event_count
Should give you a single result with the number of users attending all your events.
Lol, my original sql statement worked I was just using the wrong variable in $attendanceResult = mysqli_query($conn, $eventsSql)
Thanks anyway guys.

Mysql query based on columns matches

I don’t know how to make this with mysql, I only know how to do basic queries, I want to show a list of result based on matches, Results will be shown based on the same value of the answers…answers may have a value from 1-10
+++++++++++++++TABLE++++++++++++
id | userName | answer1 | answer2 | answer3 | answer4….
10 Jhon 1 1 3 8
11 Anne 1 2 4 8
12 Mike 7 4 5 7
etc…
++++++++++++++++++++++++++++++++++++++++
If I send the values in the query I want that check the answers and show the result sorted my matches,
more matches first…no matches last
So if i send the results:
answer1=1 answer2=1 answer3=7 answer4=2...
the result should be(give back the id)
10 11 12
Your table design is not fine, you should separate it into users and questions table.
If you cannot change the table design you can solve you problem using this query:
select
id,
username,
if(answer1 = :an1, 1, 0) + if(answer2 = :an2, 1, 0) + if(answer3 = :an3, 1, 0) + if(answer4 = :an4, 1, 0) as total
from
table
order by total desc
UPDATE:
Better design for this problem:
Check the SQLFiddle: http://sqlfiddle.com/#!9/6c145/2 with a live demo.
Create Users Table
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL
);
Create Questions Table
CREATE TABLE questions (
id INT PRIMARY KEY,
correct_answer INT NOT NULL
);
Create User Answers Table
CREATE TABLE user_answers (
user_id INT,
question_id INT,
user_answer TINYINT,
PRIMARY KEY (user_id, question_id),
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE NO ACTION ON UPDATE NO ACTION,
FOREIGN KEY (question_id) REFERENCES questions (id) ON DELETE NO ACTION ON UPDATE NO ACTION
);
Than to retrieve the data you can use the query:
SELECT
tmp.id,
tmp.username,
sum(tmp.is_correct) as total
FROM (
SELECT
users.id,
users.username,
IF (questions.correct_answer = user_answers.user_answer, 1, 0) as is_correct
FROM
users
INNER JOIN user_answers on users.id = user_answers.user_id
INNER JOIN questions on user_answers.question_id = questions.id
) tmp
GROUP BY tmp.id, tmp.username
ORDER BY total desc;

Merge records in mysql table using Laravel (or not)?

I am tracking a users activity while not logged in with a cookie_id and grouping these by date. When the user logs in I want to transfer all records from their cookie_id to their user_id. The cookie_id and user_id dates can overlap if the user is using different machines throughout the day.
For example, a user with a user_id of 1 logs in from work, but from home she doesn't so we assign her a cookie_id of 123.
The table data could look like this.
id user_id cookie_id date
2 1 NULL 2015-09-07
18 1 NULL 2015-09-10
19 NULL 123 2015-09-10
21 NULL 123 2015-09-11
22 1 NULL 2015-09-11
24 NULL 123 2015-09-12
Finally, one fine Saturday, she decides to log into her account from home.
What I would like to do is merge all of the records that have a coresponding user_id / date record, and update the row with a cookie_id of 123 with the user_id of 1 grouping by date creating any new records that are needed. I'd also like the related bananas table to be updated apprpriately as well.
id user_id cookie_id date
2 1 NULL 2015-09-07
18 1 NULL 2015-09-10
22 1 NULL 2015-09-11
24 1 NULL 2015-09-12
I am using Laravel and would like to use query builder. I have all of the code except the database query working. I am happy to post it up, if anybody thinks it is useful.
My table structure is below and I have made a SQLFiddle.
banana_groups
id int(10),
user_id int(10),
cookie_id varchar(255),
date date NOT NULL,
bananas
id int(10),
banana_group_id int(10),
monkey_id int(10),
EDIT
To embrace the spirit of SO and in response to vho's comment (which mysteriously disappeared), here is my attempt to write this SQL. Needless to say, it is incomplete and doesn't work.
Select *
FROM banana_groups AS m
WHERE EXISTS
(SELECT 1 FROM banana_groups WHERE m.user_id = 2)
AND NOT EXISTS
(SELECT 1 FROM banana_groups WHERE ...
I ended up writing a stored procedure to do this. I will leave the question unanswered so if anybody knows how to do this without a stored procedure I mark their answer correct.
CREATE PROCEDURE `transfer_bananas`(IN _cookieId VARCHAR(255), IN _userId INT)
BEGIN
DECLARE v_id INT;
DECLARE v_user_id INT;
DECLARE v_date DATE;
DECLARE v_done INT DEFAULT 0;
DECLARE cur_banana CURSOR FOR
SELECT id, `date`, (SELECT id from banana_groups
WHERE user_id = _userId AND
`date` = q.date) AS userId FROM banana_groups AS q
WHERE cookie_id = _cookieId;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = 1;
OPEN cur_banana;
loop_banana: LOOP
FETCH cur_banana INTO v_id,v_date, v_user_id;
IF v_done = 1 THEN
LEAVE loop_banana;
END IF;
IF(v_user_id IS NULL) THEN
UPDATE
banana_groups
SET
user_id = _userId,
cookie_id = NULL
WHERE
id = v_id;
ELSE
UPDATE
bananas
SET
banana_group_id = v_user_id
WHERE
banana_group_id = v_id;
DELETE FROM
banana_groups
WHERE
id = v_id;
END IF;
END LOOP loop_banana;
CLOSE cur_banana;
END
I call it from Laravel with
DB::statement(DB::raw('CALL transfer_bananas(\''
. $cookie_id
. '\', '
. $user->id
.');'
));

SQL update multiple rows with different values, without specifying unique key

I need help building a SQL query which searches for an user_id (let's say user_id = 5), but this user_id has multiple row entries, but I need to update each row differently though.
I have an array with data which I want to assign to that user_id. Here is a table example:
id user_id amount txn_id
1 5 10 foo_unique
2 5 5 bar_unique
3 7 15 xyz_unique
4 5 10 123_unique
My array would look something like this:
Array (
[0] => 14
[1] => 6
[2] => 9
)
As you see I have three array values and three rows for user_id 5, now I want to add each value of that array, to the corresponding user_id (5). Note that I have an UNIQUE column named txn_id
After updating the table, it would look like this:
id user_id amount txn_id
1 5 14 foo_unique
2 5 5 bar_unique
3 7 6 xyz_unique
4 5 9 123_unique
Any ideas how I could achieve this?
Thanks.
P.S: I cannot use SQL CASE on this issue.
If you want to update one row with a value, you have to be able to have a unique condition for that row.
Without adding some extra field, or condition to uniquely identify a row, you are out of luck.
You can use the following query:
UPDATE MyTable
SET
amount =
CASE id
WHEN 1 THEN 14
WHEN 2 THEN 6
WHEN 3 THEN 9
ELSE amount -- just in case user_id 5 has records not covered above.
END
WHERE
user_id = 5
The problem is, there is nothing on your array that says which array entry belongs to which database row. If you want to rely just on the orders (of the array indices, and the database ids,), you have to SELECT all rows for the user first, then loop and update a row at a time. Something like this on PHP (and PDO):
$values = array(14, 6, 9);
$dbh = new PDO('mysql:host=localhost;dbname=yourdbname', 'username', 'password');
$selectQuery = 'SELECT id FROM yourtable WHERE user_id = 5 ORDER BY id';
foreach($dbh->query($selectQuery) as $row) {
$id = $row['id'];
$sth = $dbh->prepare("UPDATE yourtable SET amount = :val WHERE id = :id");
$sth->execute(array(
'val' => array_unshift($values),
'id' => $id
));
}
(Code above assumes the number of values on your arrays matches the number of database rows for user_id = 5).
Looking at the problem you only need to have SQL statements.
First is to create two tables:
CREATE TABLE users
user_id int(11) PRIMARY KEY NOT NULL,
username varchar(25),
) Engine = InnoDB;
CREATE table userbalances (
balance_id int(11) PRIMARY KEY NOT NULL,
user_id int(11),
amount decimal(10,2),
CONSTRAINT userid_fk FOREIGN KEY userid_fk(user_id) REFERENCES users(userid)
) Engine = InnoDB;
Then, after you have INSERT(ed) all of the users and userbalances inside the table, all you need to do is create an UPDATE statement to update the amount:
UPDATE userbalances SET amount=? WHERE user_id=? AND balanceid=?
The update should be in a loop. And you should use mysql_query() function to update it with the assigned arrays that you have.
Note:
Both userid and balanceid should be in the WHERE clause of your UPDATE statement because you have multiple transactions inside the userbalances table. Otherwise, it's going to change all of the balances of all the transactions of that user.
Problem update:
If you don't use any SQL Cases on this problem, then your problem is just PHP. You need to find out what is the function for UPDATE(ing) - to update the amounts. As long as your tables are all prepopulated. There might be a function on the program you use to update it.

MySQL SUM() in step by step column for incomes

Database: name_ allmoney
Table name: MONEY
+-----+--------+------------+---------+---------+
| id | name | date | income | account |
+-----+--------+------------+---------+---------+
| 1 | Ann | 01.01.2012 | 100 | 100 |
| 2 | Matt | 02.01.2012 | 100 | 200 |
| 3 | Tom | 03.01.2012 | 100 | 300 |
| 4 | Peter | 04.01.2012 | 100 | 400 |
+-----+--------+------------+---------+---------+
Hello Stackoverflowers! ;)
I'm newbie for MySQL... Last week I've spend searchin for solution for above situation. I'm tryin to create script summing income column, but not only showing the sum of the column like
SELECT *, SUM(kasa) from MONEY GROUP BY id;
but I have to add new column called account, which has the option like my excel sheet:
accout1st row =income1+account1
accout2nd row =income2+account1
accout3rd row =income3+account2
accout4th row =income4+account3
Is there any code or possibility to create column like account in MySQL or PHP?
CREATE TABLE money (
id INT(11) NOT NULL AUTO_INCREMENT,
date DATE DEFAULT NULL,
income DECIMAL(11,4) DEFAULT NULL,
numer_kluczyka INT(11) DEFAULT NULL,
name CHAR(255) CHARACTER SET utf8 COLLATE utf8_polish_ci DEFAULT NULL,
za_co CHAR(255) CHARACTER SET utf8 COLLATE utf8_polish_ci DEFAULT NULL,
account INT(11) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
You can do it using a user variable -
SELECT #m := 0;
SELECT
id,
name,
date,
income,
#m := #m + income AS balance
FROM money
ORDER BY date ASC, id ASC;
The order by should use the primary key for the table.
Splitting the two queries in your PHP should fix the problem -
<?php
$connection = mysql_connect('host', 'user', 'pass') or die('failed to connect');
mysql_select_db("album", $connection) or die('failed to select db');
mysql_query("SELECT #m:=0;");
$result = mysql_query("SELECT id, imie_i_nazwisko, data_wplaty, kasa, #m := #m + income AS balance FROM money ORDER BY data_wplaty ASC , id ASC");
while($row = mysql_fetch_array($result)) {
echo $row['income'] . " " . $row['balance'];
echo "<br />";
}
If I understand your question correctly, you simply need to store the sum computed so far in your php loop.
Something like:
$account = null;
while(($result = /* read mysql result */)) {
if (is_null($account)) { // Handle first row
$account = $result['income'];
}
// Show first columns
echo $result['id'], $result['income'], $account;
$account += $result['income'];
}
Your question seems a bit unclear, but if I've guessed what you want correctly, you could do this with a subselect that sums the income column over all rows up to the current row:
SELECT id, name, date, income,
( SELECT SUM(income) FROM money AS b
WHERE b.id = a.id
AND b.date <= a.date
) AS balance
FROM money AS a
You could also do the same with a join:
SELECT a.id, a.name, a.date, a.income, SUM(b.income) AS balance
FROM money AS a
JOIN money AS b ON (b.id = a.id AND b.date <= a.date)
GROUP BY a.id, a.name, a.date, a.income
(The GROUP BY is supposed to be on the primary key of the money table. It's not entirely clear from your question what the primary key is supposed to be, since it doesn't seem to be id.)
Also note that both of these answers assume that the date columns are unique for each id and sort in ascending order by time, so that the condition b.date <= a.date can find all rows up to and including the current row. If that's not the case, you should either fix your table so that it is, or adjust the query accordingly.
Edit: S0pra's PHP solution will work too. However, the way I read your question, what you want is to sum the past income for each id separately. If so, you can use S0pra's code with a few modifications:
$balance = array();
while ( $result = mysql_fetch_assoc( $res ) ) { // or equivalent
$id = $result['id'];
if ( array_key_exists( $id, $balance ) ) {
$balance[$id] += $result['income'];
} else {
$balance[$id] = $result['income']; // handle first row for this id
}
$result['balance'] = $balance[$id];
// do something with $result here
}

Categories