How to update multiple columns from different table of MariaDB - mysql

I am using MariaDB. I am trying to update two columns from SELECT different table.
UPDATE User U
SET
U.UserPoint = (
SELECT ((SELECT COUNT(*)
FROM CARD_COMM R
WHERE R.Card_ID = C.Card_ID) * 3
+
(SELECT COUNT(*)
FROM SECTION_CARD_LIKE L
WHERE L.Card_ID = C.Card_ID) * 1) as userPoint
FROM CARD C WHERE C.userid = U.userid ORDER BY userPoint DESC limit 1 )
this works
UPDATE User U
SET
(U.UserPoint, U.Card) = (
SELECT ((SELECT COUNT(*)
FROM CARD_COMM R
WHERE R.Card_ID = C.Card_ID) * 3
+
(SELECT COUNT(*)
FROM SECTION_CARD_LIKE L
WHERE L.Card_ID = C.Card_ID) * 1) as userPoint,
C.Card_ID as card
FROM CARD C WHERE C.userid = U.userid ORDER BY userPoint DESC limit 1 )
but this dose not....
How do I do this??
please help me...

Use a multi-table update, something like
UPDATE User
JOIN ( SELECT userid, up_value, card_value ... ) AS x
ON x.userid = User.userid
SET User.UserPoint = x.up_value,
User.Card = x.card_value;
(With suitable expressions/subqueries/etc for up_value & card_value)
You seem to be updating all rows in User??

Related

How to fix join error in mysql update query

I had an error in mysql as picture. please help me
sql code is following:
UPDATE
tbl_users AS Users
SET
Users.money_current = Users.money_current +
CASE
WHEN TempTbl.money_info IS NULL
THEN 0
ELSE TempTbl.money_info
END
LEFT JOIN
(SELECT
userId,
SUM(bet_money * bet_rate) AS money_info
FROM
tbl_betting
WHERE ROUND = 'xxx'
AND is_win = 1
GROUP BY userId) AS TempTbl
ON Users.userId = TempTbl.userId
FROM tbl_users AS Users;
This is the correct syntax:
UPDATE tbl_users AS Users
LEFT JOIN (
SELECT userId, SUM(bet_money * bet_rate) AS money_info
FROM tbl_betting WHERE ROUND = '965802' AND is_win = 1
GROUP BY userId
) AS TempTbl ON Users.userId = TempTbl.userId
SET Users.money_current = Users.money_current + COALESCE(TempTbl.money_info, 0)
I also changed that CASE expression with COALESCE().
But I think an INNER JOIN would also work in your case, since the unmatched rows of the LEFT JOIN that you use do not change the value of money_current.

Get other different id

I have a simple mysql query:
SELECT U.id FROM
users U
INNER JOIN friends F
ON ( U.id = F.id_exp AND F.id_des = :id_exp )
OR ( U.id = F.id_des AND F.id_exp = :id_exp ) WHERE
U.id <> :id_des
AND F.active = 1
I wish that by calling this request again, that It does not return the id that It has already previously returned.
I hope you understand me.
Thank you.
You must give RAND a seed number in order to always get the same order. This can be any number, e.g. 1:
...
ORDER BY RAND(1)
LIMIT #offset, 1;

2 requests in only one using mysql

I have two requests
UPDATE :
I need to do something like that :
SELECT poste_nom, ups_type_contrat,
(SELECT `entpro_date`
FROM ENT_PRO
WHERE entpro_user_id = 2
ORDER BY `entpro_id` DESC
LIMIT 1) ,
serv_nom,
serv_id_resp,
user_credit_cpf,
user_indice_salarial,
FLOOR( DATEDIFF( CURDATE( ) , user_dateentree ) /365 ) AS dateEntree
FROM USER
INNER JOIN USER_POSTE_SERVICE
ON USER.user_id= USER_POSTE_SERVICE.ups_poste_id
INNER JOIN POSTE
ON USER_POSTE_SERVICE. ups_poste_id = POSTE.poste_id
INNER JOIN SERVICE
ON USER_POSTE_SERVICE.ups_id_serv = SERVICE.serv_id
WHERE user_id = 2
ORDER BY user_nom ASC
Is it possible to gather two requests in only one ?
From what I understood you want to simple merge the result of your sub-query to your main SELECT, if so you could try it this way:
SELECT poste_nom,
ups_type_contrat,
ENT_PRO_RESULT.entpro_date,
serv_nom,
serv_id_resp,
user_credit_cpf,
user_indice_salarial,
FLOOR( DATEDIFF( CURDATE( ) , user_dateentree ) /365 ) AS dateEntree
FROM USER
LEFT JOIN (SELECT entpro_date,
entpro_user_id
FROM ENT_PRO
ORDER BY entpro_id DESC
LIMIT 1) ENT_PRO_RESULT
ON USER.user_id = ENT_PRO_RESULT.entpro_user_id
INNER JOIN USER_POSTE_SERVICE
ON USER.user_id = USER_POSTE_SERVICE.ups_poste_id
INNER JOIN POSTE
ON USER_POSTE_SERVICE.ups_poste_id = POSTE.poste_id
INNER JOIN SERVICE
ON USER_POSTE_SERVICE.ups_id_serv = SERVICE.serv_id
WHERE user_id = 2
ORDER BY user_nom ASC
I've joined it on:
ON USER.user_id = ENT_PRO_RESULT.entpro_user_id
So you only need to specify the:
WHERE user_id = 2
And the sub-query will use the current row user id for the LEFT JOIN.

(My)SQL JOIN - get teams with exactly specified members

Assume tables
team: id, title
team_user: id_team, id_user
I'd like to select teams with just and only specified members. In this example I want team(s) where the only users are those with id 1 and 5, noone else. I came up with this SQL, but it seems to be a little overkill for such simple task.
SELECT team.*, COUNT(`team_user`.id_user) AS cnt
FROM `team`
JOIN `team_user` user0 ON `user0`.id_team = `team`.id AND `user0`.id_user = 1
JOIN `team_user` user1 ON `user1`.id_team = `team`.id AND `user1`.id_user = 5
JOIN `team_user` ON `team_user`.id_team = `team`.id
GROUP BY `team`.id
HAVING cnt = 2
EDIT: Thank you all for your help. If you want to actually try your ideas, you can use example database structure and data found here: http://down.lipe.cz/team_members.sql
How about
SELECT *
FROM team t
JOIN team_user tu ON (tu.id_team = t.id)
GROUP BY t.id
HAVING (SUM(tu.id_user IN (1,5)) = 2) AND (SUM(tu.id_user NOT IN (1,5)) = 0)
I'm assuming a unique index on team_user(id_team, id_user).
You can use
SELECT
DISTINCT id,
COUNT(tu.id_user) as cnt
FROM
team t
JOIN team_user tu ON ( tu.id_team = t.id )
GROUP BY
t.id
HAVING
count(tu.user_id) = count( CASE WHEN tu.user_id = 1 or tu.user_id = 5 THEN 1 ELSE 0 END )
AND cnt = 2
Not sure why you'd need the cnt = 2 condition, the query would get only those teams where all of users having the ID of either 1 or 5
Try This
SELECT team.*, COUNT(`team_user`.id_user) AS cnt FROM `team`
JOIN `team_user` ON `team_user`.id_team = `team`.id
where `team_user`.id_user IN (1,5)
GROUP BY `team`.id
HAVING cnt = 2

Set limit for MySQL query

I have query like this:
SELECT `all_messages`.`user_1`, `messages`.*, `users`.`username`
FROM `all_messages`
JOIN `messages` ON (`all_messages`.`user_2` = `messages`.`from_user`)
JOIN `users` ON (`all_messages`.`user_2` = `users`.`id`)
WHERE `all_messages`.`user_1` = '12'
ORDER BY `messages`.`sent` DESC LIMIT 2
Now this query does what I need but my problem is with this line
ON (`all_messages`.`user_2` = `messages`.`from_user`)
It selects all data from messages where the matches was found but I need only one newest record. I hope you guys get what I mean.
If you need one "newest record" you should have a date column or something, lets name it "CREATION_TIME", so you could do something like this
SELECT AM.user_1, M.*, U.username
FROM all_messages AM, messages M , users U
WHERE AM.user_1 = '12'
AND AM.user_2 = M.from_user
AND AM.user_2 = U.id
AND M.CREATION_TIME =
(
SELECT MAX(CREATION_TIME)
FROM messages
WHERE from_user= M.from_user
)
ORDER BY M.sent DESC LIMIT 2
Edit
SELECT AM.user_1, M.*, U.username
FROM all_messages AM, messages M, users U
WHERE AM.user_1 = '12'
AND AM.user_2 = M.from_user
AND AM.user_2 = U.id
AND M.sent =
(
SELECT MAX(sent)
FROM messages
WHERE from_user= M.from_user
)
ORDER BY M.sent DESC LIMIT 2
It should work