UPDATE JOIN tables, mathematical operation happens only on single (last?) row - mysql

In my application I keep track of users' total unread notifications together with other user data in user table. Notifications are in separate table, notifications of similar nature are stacked into a single row, each row tracks count and last timestamp. Now I want to implement a function of marking all notifications as read until a particular timestamp. I made this query using mathematical subtraction between two columns from two different tables:
UPDATE
core_notification n
LEFT JOIN
core_user u
ON
n.notification__user_id = u.user__id
SET
n.notification__if_read = 1,
u.user__notification_unread_count = u.user__notification_unread_count - n.notification__main_count
WHERE
n.notification__timestamp <= 123456 AND
n.notification__if_read = 0 AND
n.notification__user_id = 123;
Problem: lets say in user table "user__notification_unread_count" has a value of 4 and there are two notifications which both have a "notification__main_count" value of 2. My goal after running this query and updating both notifications as read is to have "user__notification_unread_count" value of 0 (4 - 2 - 2 = 0). However the result is always 2. I tried various join methods but it seems that it is just how databases work when updating multiple rows (each updated row overwrites previous update completely, but that is only my assumption).
Is there a way I could achieve the result I want with a single query?

This is a situation where you are probably better off using a trigger. But . . . you can do it in a single update, just with more work:
UPDATE core_notification n LEFT JOIN
core_user u
ON n.notification__user_id = u.user__id LEFT JOIN
(SELECT n2.notification__user_id,
SUM(n2.notification__main_count) as total_notification__main_count
FROM core_notification n2
WHERE n2.notification__timestamp <= 123456 AND
n2.notification__if_read = 0 AND
n2.notification__user_id = 123;
GROUP BY n2.notification__user_id
) n2
ON n2.notification__user_id = n2.notification__user_id
SET n.notification__if_read = 1,
u.user__notification_unread_count = u.user__notification_unread_count - n2.total_notification__main_count
WHERE n.notification__timestamp <= 123456 AND
n.notification__if_read = 0 AND
n.notification__user_id = 123;
The n2 derived table separately calculates the total that needs to be subtracted.

Related

Join two tables in a particular user session Mysql

I want to make a query using sql to merge two tables in a database where a particular value matches the current session id.
I'm using dreamweaver and i've added a recordset with this code but it doesn't display anything.
SELECT reg.username, reg.phoneno, gh.pay1
FROM reg INNER JOIN gh ON reg.username = gh.pay1
WHERE gh.username = colname
ORDER BY reg.id DESC
Here is the screenshot http://prntscr.com/ed0mpx
When I take out the first two lines
SELECT reg.username, reg.phoneno, gh.pay1
FROM reg INNER JOIN gh ON reg.username = gh.pay1
It only display record for the first row. Other record doesn't show

MySQL clubbing two rows as a single one

I have a table called connections for a friendship system. The columns are:
id, from,to,direction,liking
Whenever a user sends a friend request, a row is added and direction is set to 1 (1 for forward, 2 for reverse). When the other user accepts the friend request, another row is added and the direction is set to 2.
I'm trying to figure out a way to get a user's friends. But when I do the following query, rows are repeated.
SELECT
`users`.`name`,`users`.`id`
FROM
`connections`,
`users`
WHERE
(
`connections`.`from` = 1234 AND
`connections`.`to` = `users`.`id` AND
`connections`.`direction` = 1
)
OR
(
`connections`.`to` = 1234 AND
`connections`.`from` = `users`.`id` AND
`connections`.`direction` = 2
)
How can this query be modified to include so that rows don't repeat?
Update: I'm adding two rows because there's a column liking. This value is different for "distinct user connections".
Example -A can have a liking of 0.95 for B. And B can have a liking of just 0.25 for A.
Based on your comments, you can add an outer query:
SELECT
name, DISTINCT(id) AS id
FROM
(original query)
You say that you add a row when the friend accepts the request. That creates two rows. Would it not make more sense to update the existing row with the new direction? - ignore this last part as per comment

Removing duplicate user entries from mySQL database table

I have a table in my database to store user data. I found a defect in the code that adds data to this table database where if a network timeout occurs, the code updated the next user's data with the previous user's data. I've addressed this defect but I need to clean the database. I've added a flag to indicate the rows that need to be ignored and my goal is to mark these flags accordingly for duplicates. In some cases, though, duplicate values may actually be legitimate so I am more interested in finding several user's with the same data (i.e, u> 2).
Here's an example (tablename = Data):
id---- user_id----data1----data2----data3----datetime-----------flag
1-----usr1--------3---------- 2---------2---------2012-02-16..-----0
2-----usr2--------3---------- 2---------2---------2012-02-16..-----0
3-----usr3--------3---------- 2---------2---------2012-02-16..-----0
In this case, I'd like to mark the 1 and 2 id flags as 1 (to indicate ignore). Since we know usr1 was the original datapoint (assuming the oldest dates are earlier in the list).
At this point there are so many entries in the table that I'm not sure the best way to identify the users that have duplicate entries.
I'm looking for a mysql command to identify the problem data first and then I'll be able to mark the entries. Could someone guide me in the right direction?
Well, first select duplicate data with their min user id:
CREATE TEMPORARY TABLE duplicates
SELECT MIN(user_id), data1,data2,data3
FROM data
GROUP BY data1,data2,data3
HAVING COUNT(*) > 1 -- at least two rows
AND COUNT(*) = COUNT(DISTINCT user_id) -- all user_ids must be different
AND TIMESTAMPDIFF( MINUTE, MIN(`datetime`), MAX(`datetime`)) <= 45;
(I'm not sure, if I used TIMESTAMPDIFF properly.)
Now we can update the flag in those rows where user_id is different:
UPDATE duplicate
INNER JOIN data ON data.data1 = duplicate.data1
AND data.data2 = duplicate.data2
AND data.data3 = duplicate.data3
AND data.user_id != duplicate.user_id
SET data.flag = 1;
UPDATE Data A
LEFT JOIN
(
SELECT user_id,data1,data2,data3,min(id) min_id
FROM Data GROUP BY user_id,data1,data2,data3
) B
ON A.id = B.min_id
SET A.flag = IF(ISNULL(B.min_id),1,0);
If there are duplicate times involved, maybe try this
UPDATE Data A
LEFT JOIN
(
SELECT user_id,data1,data2,data3,,`datetime`,min(id) min_id
FROM Data GROUP BY user_id,data1,data2,data3,`datetime`
) B
ON A.id = B.min_id
SET A.flag = IF(ISNULL(B.min_id),1,0);

MySQL Update Join Does not Affect ALL matching rows

I am attempting to do an UPDATE with a JOIN. I have two tables:
player_tracking has a list of all
players that each user has added to
tracking.
users is the user list. each user
can set fsp_f to 1 or 0.
I want to update all rows in player_tracking for users who have fsp_f set to 1. Here is my example code:
UPDATE player_tracking AS pt
LEFT JOIN users AS u ON u.name = pt.user
SET pt.newtome = pt.newtome - 1
WHERE pt.first = 'Brett'
AND pt.last = 'Gardner'
AND pt.sport = 'mlb'
AND u.fsp_f = 1
The problem is that there are 22 rows to update, yet the UPDATE query only affects 2. Why? Is my query wrong?
Here is the data found in player_tracking pertaining to "Brett" "Gardner" "mlb":
http://pastebin.com/kyf8SCy8
i believe that if you change the LEFT JOIN to JOIN you will see the exact rows that get updated since you are using a field form users in the WHERE part of the statement.
so basically you are trying to check if u.fsp_f = 1 when there could be rows that do not join users and therefore will have the value as NULL.
Additionally it seems that the general layout of your query is not correct either, since you are joining on the SET statement and not in the UPDATE part - where you instructed which table to update

Mysql combining multiple rows into one row dependant upon a single field?

I have three tables, table one (tableA) containing users data like name and email, another (tableB) flagging if they wish to receive an email or sms notice and a last table (tableC) noting which type of notices they require out of four types.
tableA and tableB have single rows for each user, but tableC could have up to 4 entries.
Is it possible I can concatinate the multiple entries of tableC in to a single row return, additionally with my other data from my other two tables. Perhaps building some sort of comma delimited field in the row?
I currently have this as my mySQL query:
SELECT
ppf.page_id,
prv.`name`,
prv.surname,
prv.email,
prv.mobile,
ppf.email,
ppf.sms,
page_profile_noticetypes.noticetype
FROM
page_registration_value AS prv
Inner Join page_profile_value AS ppf ON prv.page_id = ppf.user
Inner Join page_profile_noticetypes ON page_profile_noticetypes.page_id = ppf.page_id
WHERE ppf.sms = 1 OR ppf.email = 1
#itsadok answered it - Result:
SELECT
ppf.page_id,
prv.`name`,
prv.surname,
prv.email,
prv.mobile,
ppf.email,
ppf.sms,
GROUP_CONCAT(page_profile_noticetypes.noticetype)
FROM
page_registration_value AS prv
Inner Join page_profile_value AS ppf ON prv.page_id = ppf.user
Inner Join page_profile_noticetypes ON page_profile_noticetypes.page_id = ppf.page_id
WHERE ppf.sms = 1 OR ppf.email = 1
GROUP BY prv.email