UPDATE JOIN, wrong data insertion - php

So i have this two tables, the operators_payments AS op is populated with data, but the op.date_paid will be NULL, till payment date arrives, when this happens, the payment_process AS pp table is used to initialize the payment (pp.date_started is set to NOW()), then for payment completion the op.date_paid is set to pp.date_started. The shown query, is used to do this, all is good, but when all records are updated, one of the records and only one gets the op.date_paid with different time, specifically the second part e.g.(time set to all but one: 2012-07-05 17:28:14, time set to one: 2012-07-05 17:28:02).
Im using Mysql 5.5, the columns have the same type (TIMESTAMP).
I need this because i need the date to be exact as the one in pp.date_started.
My question is, Why does this happens, and what can i do to have this as espected?
UPDATE operators_payments AS op
JOIN payment_process AS pp
ON op.operator_id = pp.operator_id
AND pp.type = 0
AND pp.status = 1
SET op.date_paid = pp.date_started, pp.status = 2, pp.message=CONCAT(SUBSTRING_INDEX(message, '|', 1), '| was completed successfully!')
WHERE op.operator_id = {$this->operator_id}
AND op.date_paid IS NULL
AND op.date_end <= pp.date_accounted
+---------------+-----------------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-----------------------+------+-----+-------------------+----------------+
| payment | int(10) unsigned | NO | PRI | NULL | auto_increment |
| operator_id | int(10) unsigned | NO | MUL | 0 | |
| date_paid | timestamp | YES | MUL | NULL | |
| date_start | timestamp | YES | | NULL | |
| date_end | timestamp | YES | MUL | NULL | |
| amount | decimal(6,4) unsigned | NO | | 0.0000 | |
+---------------+-----------------------+------+-----+-------------------+----------------+
+----------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+-------------------+-----------------------------+
| operator_id | int(11) | NO | PRI | NULL | |
| type | tinyint(4) | NO | PRI | NULL | |
| date_started | timestamp | YES | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| date_accounted | timestamp | YES | | NULL | |
| amount | decimal(6,4) | YES | | NULL | |
| status | tinyint(4) | YES | MUL | 0 | |
| message | varchar(255) | YES | | NULL | |
+----------------+--------------+------+-----+-------------------+-----------------------------+

I have a suspicious eye toward that on update CURRENT TIMESTAMP clause on the date_started on payment_process... I'm not actually sure what it could be doing in this query, but you are updating that table in this query, and using that value. I also don't like the semantic discord of a column called date_started which has it's value changed on every update... but I don't know how it's used. I would evaluate if that clause is necessary on that column, and see if you get this strange behavior without it,

Related

MYSQL Trigger() vs. Delete permanently

I have two tables as below:
Table Job_Announcement used to store information about Job, defined as below:
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| job_id | int(11) | NO | PRI | NULL | auto_increment |
| job_title | varchar(255) | NO | | NULL | |
| category | varchar(255) | NO | | NULL | |
| term | varchar(255) | NO | | NULL | |
| num_experiences | int(11) | NO | | NULL | |
| num_hiring | int(11) | NO | | NULL | |
| Salary | varchar(255) | NO | | NULL | |
| qualification | varchar(255) | NO | | NULL | |
| location | varchar(255) | NO | | NULL | |
| gender | varchar(255) | NO | | NULL | |
| job_content | text | NO | | NULL | |
| job_requirement | varchar(255) | NO | | NULL | |
| publish_date | date | NO | | NULL | |
| close_date | date | NO | | NULL | |
| contact_info | varchar(255) | NO | | NULL | |
| userid | varchar(255) | NO | | NULL | |
| publish | tinyint(1) | NO | | NULL | |
+-----------------+--------------+------+-----+---------+----------------+
And Table job_announcement_deleted, used to store deleted record from table job_announcement
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| job_id | int(11) | NO | PRI | NULL | auto_increment |
| job_title | varchar(255) | NO | | NULL | |
| category | varchar(255) | NO | | NULL | |
| job_content | text | NO | | NULL | |
| publish_date | date | NO | | NULL | |
| close_date | date | NO | | NULL | |
| userid | varchar(255) | NO | | NULL | |
| publish | tinyint(1) | NO | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
In order to move deleted record from job_announcement table to job_announcement_deleted table, I defined trigger definition in phpmyadmin like this:
Trigger Name: before_delete_job
Table: job_announcement
Time: BEFORE
Event: Delete
Definition:
BEGIN
INSERT INTO job_announcement_deleted VALUES(old.job_id,old.job_title,old.category,old.job_content,old.publish_date,old.close_date,old.userid,old.publish);
END
Definer: root#localhost
The trigger event before_delete_job is working fine that the deleted record moved to table job_announcement_deleted.
My problem is if I want to restore deleted record back to table job_announcement, I define similar trigger definition event like above, ex. job_announcement_restore for tale job_announcement_deleted however, how can I do if I want to delete record permanently from job_announcement_deleted? because I want user have options either to restore it or to deleted permanantly.
Thanks.
For the restore just do the reverse process you did for delete (sending data from job_announcement_deleted to job_announcement)
For the perma delete you just have to get the job_id field, since it's auto-incremeneted making it unique for every job.
After you acquire job_id from the user (e.g if he clicks delete from this row you extract job_id from that row), just use DELETE FROM like this :
DELETE FROM job_announcement_deleted WHERE job_id = #job_id
(where #job_id will be the one you acquired earlier in the process)
Also, you shouldn't be sending job_id to the job_announcement_deleted table, since the field is auto-increment, meaning it'll add a new value (incremented by 1 by default) for that field, so there are no duplicates for that field. You just destroy the meaning of auto-increment by doing that, specially since primary key must be a unique value. You could have trouble later on with the database if you get duplicate values for that field, so I suggest you just leave that field unfilled so auto-increment can do it's job.

What is the best way to update a one table from another in SQL?

I have 2 tables the first one is the product-page visited
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| idproduct | varchar(128) | YES | | NULL | |
| logdate | date | YES | | NULL | |
| idmagasin | int(20) | YES | | NULL | |
| idenseigne | int(20) | YES | | NULL | |
| commanded | int(2) | YES | | 0 | |
+------------+--------------+------+-----+---------+----------------+
And the second one is the product commanded
+-------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| idproduct | varchar(255) | NO | | NULL | |
| idenseigne | int(11) | NO | | NULL | |
| idmagasin | int(11) | NO | | NULL | |
| ingredients | tinytext | YES | | NULL | |
| date | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------------+--------------+------+-----+-------------------+----------------+
How can i update the column commanded in product_visited , if product_visited.idproduct = product_commanded.idproduct and product_visited.logdate = product_commanded.date
i'm confused to use inner join or exists
I want to update product_visited.commanded = 1 when the value of logdate and idproduct exists in product_commanded, it will mean the product visited is commanded too
I believe this is what you are looking for:
Update product_visited pv
set commanded = 1
Where exists (Select 1
from product_commanded pc
where pv.idproduct = pc.idproduct and pv.logdate = pc.date
);
Ok, I've made guesses with the join fields but you're after something like this;
UPDATE pv
SET pv.Commanded = 1
FROM Product_Visited pv
JOIN Product_Commanded pc
ON pv.logdate = pc.date
AND pv.idproduct = pc.id
The inner join means that you're only going to update records in Product_Visited where there are matching rows in Product_Commanded based on the join predicates you give it.
Note: this is a SQL Server answer. May or may not work in MySQL
Sounds like you want to update commanded whenever a record exists for same product in commanded table?
in any database:
Update product_visited set commanded = 1
Where exists(Select * from product_commanded
where product_id = product_visited.Product_id)

Doing a proper Join with SQL

Suppose I have two tables, one with list of spells and another with a grimory, the list of spells that a user has selected for learn or already learned.
mysql> SHOW COLUMNS FROM Grimory;
+--------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| personage_id | int(11) | YES | MUL | NULL | |
| spell_id | int(11) | YES | MUL | NULL | |
| isLearned | tinyint(1) | NO | | NULL | |
| isSelected | tinyint(1) | NO | | NULL | |
+--------------+------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql> SHOW COLUMNS FROM Spell;
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| description | longtext | NO | | NULL | |
| chatDescription | longtext | NO | | NULL | |
| level | int(11) | NO | | NULL | |
| isActive | tinyint(1) | NO | | NULL | |
| category_id | int(11) | YES | MUL | NULL | |
| createdAt | datetime | YES | | NULL | |
+-----------------+--------------+------+-----+---------+----------------+
8 rows in set (0.00 sec)
The problem.
I want to display a list with ALL spells by category_id, BUT for every row I want to show if that spell is learned or selected by current user (personage_id).
Can you help me to write a proper query?
How this works:
With php I generate: List of spells | checkbox isSelected | checkBox isStudied
When I click on isSelected checkbox, a record in grimory will be added with current user and spell.
Updated
SELECT a.*, IFNULL(b.isLearned,0) as isLearned,
IFNULL(b.isSelected,0) as isSelected
FROM Spell a
LEFT JOIN Grimory b(ON b.spell_id =a.id
AND b.personage_id =:current_user_id)
WHERE a.category_id = :current_category_id
SELECT * FROM Spell
INNER JOIN Grimory
ON Spell.id = Grimory.spell_id
WHERE (Grimory.isLearned = 1 OR Grimory.isSelected = 1)
AND Spell.category_id = 'YOUR CAT ID IS HERE'

Mysql multiple timestamp column update

Consider this:
+---------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+-------------------+-----------------------------+
| email_address | varchar(100) | NO | PRI | NULL | |
| create_date | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| optin_date | timestamp | YES | | NULL | |
| optout_date | timestamp | YES | | NULL | |
+---------------+--------------+------+-----+-------------------+-----------------------------+
Using PHP, how can I make the optin_date and optout_date columns store the current timestamp?
You can have only one current_timestamp column. For the second you have to use trigger on insert/update.
http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html

Force Specific Record to Top When Performing GROUP BY

I have the following MySQL query and tables from which I am querying:
SELECT
`Song`.`id`,
`Song`.`file_name`,
`User`.`first_name`,
`Vote`.`value`,
Sum(`Vote`.`value`) AS score
FROM `songs` AS `Song`
LEFT JOIN votes AS `Vote` ON (`Song`.`id`=`Vote`.`song_id`)
LEFT JOIN `users` AS `User` ON (`Song`.`user_id` = `User`.`id`)
GROUP BY `Vote`.`song_id`
LIMIT 20;
mysql> describe songs;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| file_name | varchar(255) | NO | | NULL | |
| user_id | int(11) | NO | | NULL | |
| created | datetime | NO | | NULL | |
| modified | datetime | NO | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql> describe users;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(255) | NO | | NULL | |
| password | varchar(255) | NO | | NULL | |
| first_name | varchar(255) | NO | | NULL | |
| last_name | varchar(255) | NO | | NULL | |
| is_admin | tinyint(1) | NO | | 0 | |
| created | datetime | NO | | NULL | |
| modified | datetime | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
mysql> describe votes;
+----------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| value | int(11) | NO | | NULL | |
| song_id | int(11) | NO | | NULL | |
| user_id | int(11) | NO | | NULL | |
| created | datetime | NO | | NULL | |
| modified | datetime | NO | | NULL | |
+----------+----------+------+-----+---------+----------------+
This query functions just like I want except for one thing. The value returned in the field Vote.value is not from a row that is associated with the user who is logged into the application. I need the score value to be a sum of all the values no matter which user it is associated with, but the Vote.value field should belong to the logged in user (each user only gets one vote record per song).
My first thought is to somehow sort the table so that when the group by happens the vote record for the logged in user is at the top but I have no idea how to do a sort that forces an arbitrary value to the top. Any ideas would be very helpful.
and a third join
LEFT JOIN votes AS `VotePerUser` ON (`Song`.`id`=`Vote`.`song_id`
AND `Song`.`user_id`=`votes`.`user_id`)
and replace the Vote.value with VotePerUser.Value

Categories