Update two tables at once, using values from first table - mysql

So I need to Update table scores and use the updated value of column won to update the second table tbl_users. So far the code updates scores, but uses the old value of won for the second table update:
UPDATE scores a
left join tbl_users b on
a.uid = b.userID
SET a.won = CASE
WHEN a.nright = '0' THEN '0'
WHEN a.nright = '1' THEN '25'
WHEN a.nright = '2' THEN '50'
WHEN a.nright = '3' THEN '100'
WHEN a.nright = '4' THEN '200'
WHEN a.nright = '5' THEN '400'
WHEN a.nright = '6' THEN '700'
WHEN a.nright = '7' THEN '1000'
END,
b.pts=b.pts+a.won,
b.pts_total=b.pts_total+a.won
WHERE a.uid=$user AND b.userID=$user

What you want to do is explicitly documented as correct:
The second assignment in the following statement sets col2 to the
current (updated) col1 value, not the original col1 value. The result
is that col1 and col2 have the same value. This behavior differs from
standard SQL.
UPDATE t1 SET col1 = col1 + 1, col2 = col1;
I assume that the issue is the multi-table update, where the set pulls the value from the earlier table.
You may be able to fix this using variables. I am not 100% sure, but the following is worth a try:
UPDATE scores s JOIN
tbl_users u
ON s.uid = .uuserID
SET s.won = (#w := (CASE WHEN s.nright = '0' THEN '0'
WHEN s.nright = '1' THEN '25'
WHEN s.nright = '2' THEN '50'
WHEN s.nright = '3' THEN '100'
WHEN s.nright = '4' THEN '200'
WHEN s.nright = '5' THEN '400'
WHEN s.nright = '6' THEN '700'
WHEN s.nright = '7' THEN '1000'
END)
),
u.pts = u.pts + #w,
u.pts_total = u.pts_total + #w
WHERE s.uid = $user ;
The documentation strongly suggests that the set clauses are processed in order for a single table. Alas, it is not clear whether this is always true for multiple tables.
If not, you can use two updates.

Related

Case statement not working with or condition

Please help me with this code.
SELECT (CASE LEFT(BRANCH_CODE, 1)
WHEN '1' THEN 'NL'
WHEN '2' THEN 'MM'
WHEN '3' THEN 'SL'
WHEN '4' THEN 'VIS'
WHEN '5' THEN 'MIN'
WHEN ('7' OR '8') THEN 'SA'
END) `REGION`,
This is the result:
Region
null
MM
The result should be like this:
Region
SA
MM
The following syntax is not valid:
WHEN ('7' OR '8') THEN 'SA'
What follows WHEN or ELSE using this style of CASE expression can only be a literal value, not a logical expression. So, you could refactor to:
SELECT
CASE LEFT(BRANCH_CODE, 1)
WHEN '1' THEN 'NL'
WHEN '2' THEN 'MM'
WHEN '3' THEN 'SL'
WHEN '4' THEN 'VIS'
WHEN '5' THEN 'MIN'
WHEN '7' THEN 'SA' -- repeat the 'SA' predicate twice
WHEN '8' THEN 'SA' END AS REGION
FROM yourTable;
If you wanted to combine the 7 and 8 cases in a single WHEN, then you would have to use the longer form of CASE:
SELECT
CASE WHEN LEFT(BRANCH_CODE, 1) = '1' THEN 'NL'
WHEN LEFT(BRANCH_CODE, 1) = '2' THEN 'MM'
WHEN LEFT(BRANCH_CODE, 1) = '3' THEN 'SL'
WHEN LEFT(BRANCH_CODE, 1) = '4' THEN 'VIS'
WHEN LEFT(BRANCH_CODE, 1) = '5' THEN 'MIN'
WHEN LEFT(BRANCH_CODE, 1) = '7' OR
LEFT(BRANCH_CODE, 1) = '8' THEN 'SA' END AS REGION
FROM yourTable;
This second version is fairly ugly IMHO, and I would probably stick with the first version, which just repeats the SA predicate in two places.
I had similar issues when trying to apply multiple condition statements in "CASE" statement.
I solved it by moving the test after the "WHEN" statement as following :
SELECT (CASE
WHEN LEFT(BRANCH_CODE, 1) = '1' THEN 'NL'
WHEN LEFT(BRANCH_CODE, 1) = '2' THEN 'MM'
WHEN LEFT(BRANCH_CODE, 1) = '3' THEN 'SL'
WHEN LEFT(BRANCH_CODE, 1) = '4' THEN 'VIS'
WHEN LEFT(BRANCH_CODE, 1) = '5' THEN 'MIN'
WHEN LEFT(BRANCH_CODE, 1) IN ('7' OR '8') THEN 'SA'
END) `REGION`,

mysql multiple values () include, need update based on condition

I need to update the fields on duplicate key if one columns value is equal to soemthing. Right now I have something like this:
INSERT INTO `table` (metric,amount,something1,something2)
VALUES (metric,amount,something1,something2),
(metric,amount,something1,something2),
(metric,amount,something1,something2)
ON DUPLICATE KEY UPDATE
amount = IF (metric = '6', amount = amount + ( '"+amount+"'),'')
ELSEIF (metric = '8' , amount = amount + ( '"+impressions+"') ,'')
ELSEIF (metrtic = '11' , amount = amount + ( '"+impressions+"') ,'');
What am I doing wrong here?
If I understand correctly, you can use UPDATE , self JOIN With CASE WHEN
[DUPLICATE KEY] can fill you want to check DUPLICATE column.
UPDATE `table` r
JOIN (
SELECT Count(*) cnt,[DUPLICATE KEY]
from `table`
group by [DUPLICATE KEY]
) t1 on r.[DUPLICATE KEY] = t1.[DUPLICATE KEY] and t1.cnt > 1
SET r.amount = (CASE WHEN r.metric = '6' THEN r.amount+ ( '"+amount+"'),''
WHEN r.metric = '8' THEN r.amount + ( '"+impressions+"') ,''
WHEN r.metric = '11' THEN r.amount+ ( '"+impressions+"') ,''
ELSE r.amount
END)
What eventually worked for me is:
INSERT INTO `table` (metric,amount,something1,something2)
VALUES (metric,amount,something1,something2),
(metric,amount,something1,something2),
(metric,amount,something1,something2)
ON DUPLICATE KEY UPDATE
metric = VALUES(metric),
amount = amount + VALUES (amount),
modified = NOW(),
something1= VALUES(something1);
Hope this helps anyone in the future.

Shorten the mysql case query

I have written this query but it seems a very bad query,
select * from games_applied where
games_post_id='1126' and status != '4' and
(status != '5' and rejected_status = '0' or status = '5' and rejected_status = '1');
How to make use of this case in a better way.
(status != '5' and rejected_status = '0' or status = '5' and rejected_status = '1')
should only display the rows which has rejected_status = 1 and status = 5
and should not display the rows which has rejected_Status = 0 and status = 5
This is not a major simplification, but it does remove the comparison to 4. However, this is how I would write the query:
select ga.*
from games_applied ga
where ga.games_post_id = 1126 and
( (ga.status not in (4, 5) and ga.rejected_status = 0) or
(ga.status = 5 and ga.rejected_status = 1)
);
Notes:
The table has a meaningful table alias.
All the column names are qualified.
I assume that the numbers are really comparisons for numeric columns, so I removed the single quotes.
I removed the comparison to "4".
The only improvements that your query needs, is to encapsulate the two clauses on either side of your or statement. In other words, put your status and rejected_status check inside parentheses.
select
*
from
games_applied
where
games_post_id='1126'
and status != '4'
and
(
(status != '5' and rejected_status = '0')
or (status = '5' and rejected_status = '1')
);
Here is the query hopefully it works as required :
select * from games_applied where
games_post_id='1126' and status != '4' and case when status='5' then
rejected_status='1' else rejected_status='0' end;

not retrieving exact result from case statement

I am using below query but Y column not retrieving exact result. Could you guys please help me out
SELECT FAPI.*,
CASE WHEN (SELECT DISTINCT 'Y'
FROM FLOOR_PI FAPI,
NUATON NUMF
WHERE FAPI.BRCH = NUMF.BRCH
AND FAPI.BASE = NUMF.BASE
AND FAPI.NUM = 0
AND NVL(FAPI.RATION, 'X') <> 'D'
AND FAPI.CODE = 'A'
AND NUMF.R_DATE
BETWEEN FAPI.EFF_DATE
AND FAPI.EXP_DATE ) = 'Y'
THEN 'Y'
ELSE 'N' END NEW
FROM FLOOR_PI FAPI
Thank you,
Rave
Based on #SlimsGohst comment:
You should replace FAPIx with FAPI1 or FAPI2 whichever is applicable
SELECT FAPI1.*,
CASE WHEN (SELECT DISTINCT 'Y'
FROM FLOOR_PI FAPI2,
NUATON NUMF
WHERE FAPIx.BRCH = NUMF.BRCH
AND FAPIx.BASE = NUMF.BASE
AND FAPIx.NUM = 0
AND NVL(FAPIx.RATION, 'X') <> 'D'
AND FAPIx.CODE = 'A'
AND NUMF.R_DATE
BETWEEN FAPIx.EFF_DATE
AND FAPIx.EXP_DATE ) = 'Y'
THEN 'Y'
ELSE 'N' END NEW
FROM FLOOR_PI FAPI1

Finding difference resullts in subquery returns more than 1 row in mysql error

I have a table named tbl_populations having following fields:
pk_populationid,residence,value,aspect,gender,fk_tbl_states_stateid
I am trying to calculate the difference of rows for two aspects
for e.g.
SELECT fk_tbl_states_stateid, value - (
SELECT value
FROM tbl_populations
WHERE fk_tbl_states_stateid = '16'
AND fk_tbl_districts_districtid = '0'
AND residence = '0'
AND gender = '0'
AND aspect = '2' ) AS difference
FROM tbl_populations
WHERE fk_tbl_states_stateid = '16'
AND fk_tbl_districts_districtid = '0'
AND residence = '0'
AND gender = '0'
AND aspect = '1'
It is working fine as it returns one row
For fetching multiple data that is i want to retrieve all gender values , i have removed the gender from the condition.
SELECT fk_tbl_states_stateid,gender, value - (
SELECT value
FROM tbl_populations
WHERE fk_tbl_states_stateid = '16'
AND fk_tbl_districts_districtid = '0'
AND residence = '0'
AND aspect = '2' ) AS difference
FROM tbl_populations
WHERE fk_tbl_states_stateid = '16'
AND fk_tbl_districts_districtid = '0'
AND residence = '0'
AND aspect = '1'
I am getting Subquery returns more than 1 row error.
How can i get the all results?
SELECT Table11.fk_tbl_states_stateid,Table1.Gender,Table1.value - table2.Value as Diff
From
(SELECT *
FROM tbl_populations
WHERE fk_tbl_states_stateid = '16'
AND fk_tbl_districts_districtid = '0'
AND residence = '0'
AND aspect = '2' ) Table1,
(SELECT value,Gender
FROM tbl_populations
WHERE fk_tbl_states_stateid = '16'
AND fk_tbl_districts_districtid = '0'
AND residence = '0'
AND aspect = '1' ) Table2
Where Table1.Gender = Table2.Gender
use a function for it , should be easy that way