Update Value in next Row MYSQL - mysql

What should i query to update the next ROW2 and so on which will be deducted from previous row.
Update tbl SET BAL= ''
Row 1 which has 10 QTY and 5 BAL
on the next Row 2, get the Previous BAL which is 5 then substract 1 QTY in Row 2, then update the Row 2 BAL = 4 and so on.
My Table
Row
QTY
BAL
1
10
5
2
1
0
3
4
0
DESIRED OUTPUT
Row
QTY
BAL
1
10
5
2
1
4
3
4
0

UPDATE MyTable, ( SELECT `Row`, `QTY`,
#balance := #balance - QTY AS BAL
FROM MyTable
CROSS JOIN ( SELECT #balance := QTY + BAL
FROM MyTable
ORDER BY `Row` LIMIT 1 ) as init
ORDER BY `Row` ASC) data_for_update
SET MyTable.BAL = data_for_update.BAL
WHERE MyTable.`Row` = data_for_update.`Row`;
fiddle
UPDATE MyTable
JOIN ( SELECT t1.`Row`, t1.QTY, t3.init_balance - SUM(t2.QTY) BAL
FROM MyTable t1
JOIN MyTable t2 ON t1.`Row` >= t2.`Row`
CROSS JOIN ( SELECT QTY + BAL init_balance
FROM MyTable
ORDER BY `Row` LIMIT 1 ) t3
GROUP BY t1.`Row`, t1.QTY, t1.BAL, t3.init_balance) data_for_update
ON MyTable.`Row` = data_for_update.`Row`
SET MyTable.BAL = data_for_update.BAL;
fiddle

Related

mysql find three consecutive rows with the same value

I have read a few similar questions on counting consecutive rows, but none of them gave me a clear answer. I hope someone could give me some help with my problem. I have the following table data:
ID TEST_VALUES
1 A
2 B
3 C
4 C
5 C
6 C
7 A
8 D
9 D
10 D
11 B
12 C
13 C
14 C
15 C
now I want to find three consecutive rows with the same value within the ID range is 1 to 10,such as when the ID range is 1 to 10,there has the 'C' continuous appear more than three times.
(note: this question has nothing to do with ID,The column ID is only the condition for my query,such as where ID > 1 and ID < 10)
you can try this one,
SELECT TEST_VALUES, MAX(cnt) AS maxCount
FROM (
SELECT TEST_VALUES, ID, COUNT(grp) AS cnt
FROM (
SELECT ID, TEST_VALUES, rn - rnByVal AS grp
FROM (
SELECT ID, TEST_VALUES,
#rn := #rn + 1 AS rn,
#rnByVal := IF (#val = TEST_VALUES,
IF (#val := TEST_VALUES, #rnByVal + 1, #rnByVal + 1),
IF (#val := TEST_VALUES, 1, 1)) AS rnByVal
FROM mytable
CROSS JOIN (SELECT #rn := 0, #rnByVal := 0, #val := '') AS vars
ORDER BY ID) AS t
) AS s
GROUP BY TEST_VALUES, grp ) AS u
GROUP BY TEST_VALUES
It will be return maximum count for occurring consecutive rows with the same value(more then 1).
I also think of a solution,hoping to help others
SELECT
TEST_VALUES
FROM(
SELECT
m.TEST_VALUES AS TEST_VALUES,
IF(#b = m.TEST_VALUES, #a := #a +1, #a := 0) AS countNUM,
#b := m.TEST_VALUES
FROM tableName m
JOIN (
SELECT
#a := 0
) AS t
) AS TEMP
WHERE countNUM >= 2
GROUP BY TEST_VALUES
SELECT
GROUP_CONCAT(`TEST_VALUES` ORDER BY `id` ASC) AS g
FROM
`tbl`
WHERE
`ID` >=1 AND `ID` <= 10
HAVING
g LIKE '%C,C,C,C%'
Ordering the GROUP_CONCAT() by id ensures the results are sequential. The HAVING clause extracts only those rows which contain at least four sequential instances of C.
Convoluted, but tested and working:
SELECT t1.ID AS t1_id, t1.TEST_VALUES AS t1_values,
(SELECT ID FROM test WHERE test.ID > t1.ID LIMIT 1 ) AS t2_id, (SELECT TEST_VALUES FROM test WHERE test.ID > t1.ID LIMIT 1 ) AS t2_values,
(SELECT ID FROM test WHERE test.ID > (SELECT ID FROM test WHERE test.ID > t1.ID LIMIT 1 ) LIMIT 1 ) AS t3_id, (SELECT TEST_VALUES FROM test WHERE test.ID > (SELECT ID FROM test WHERE test.ID > t1.ID LIMIT 1 ) LIMIT 1 ) AS t3_values,
(SELECT ID FROM test WHERE test.ID > (SELECT ID FROM test WHERE test.ID > (SELECT ID FROM test WHERE test.ID > t1.ID LIMIT 1 ) LIMIT 1 ) LIMIT 1 ) AS t4_id, (SELECT TEST_VALUES FROM test WHERE test.ID > (SELECT ID FROM test WHERE test.ID > (SELECT ID FROM test WHERE test.ID > t1.ID LIMIT 1 ) LIMIT 1 ) LIMIT 1 ) AS t4_values
FROM test AS t1
HAVING (
ID BETWEEN 1 AND 10 AND t2_id BETWEEN 1 AND 10 AND t3_id BETWEEN 1 AND 10 AND t4_id BETWEEN 1 AND 10
AND
t1_values = t2_values AND t2_values = t3_values AND t3_values = t4_values
)
Gives these results:
+-------+-----------+-------+-----------+-------+-----------+-------+-----------+
| t1_id | t1_values | t2_id | t2_values | t3_id | t3_values | t4_id | t4_values |
+-------+-----------+-------+-----------+-------+-----------+-------+-----------+
| 3 | C | 4 | C | 5 | C | 6 | C |
+-------+-----------+-------+-----------+-------+-----------+-------+-----------+
1 row in set (0.03 sec)

Insert a new column based on existing column values

I have a table table1 in mysql like this:
price item count
100 xyz 5
200 xyz 1
300 xyz 4
400 abc 1
500 abc 2
I want to insert a new column 'new_price' that will hold the 'price' for that 'item' with the highest 'count'. So the new table will be
price item count new_price
100 xyz 5 100
200 xyz 1 100
300 xyz 4 100
400 abc 1 500
500 abc 2 500
What is the most efficient way of doing this? Thanks very much for your help.
I think the easiest approach is to use variables:
select t.*,
(#price := if(#i = item, #price,
if(#i := item, price, price)
)
) as new_price
from table1 t cross join
(select #i := '', #price := -1) vars
order by item, count desc;
If you actually want to update values in the table, you can fit this into an update as well:
update table1 t join
(select t.*,
(#price := if(#i = item, #price,
if(#i := item, price, price)
)
) as new_price
from table1 t cross join
(select #i := '', #price := -1) vars
order by item, count desc
) tp
on tp.item = t.item and tp.price = t.price and tp.count = t.count
set t.new_price = tp.price;

Select from a select statement from a defined value

I've the following table structure:
id |name |date
1 a 2012-01-01
2 a 2011-01-01
3 a 2010-01-01
4 a 2014-01-01
5 a 2011-01-01
I'd like to perform a select order by date (desc), and after select the first 3 rows from the results by a condition which would be where id = 1. So the second part of the query would be "give me the first 3 rows starting from the row whose id equals to 1"
EDIT:
After the first "part" the result would be:
SELECT id, name, date FROM table ORDER BY date DESC
id |name |date
4 a 2014-01-01
1 a 2012-01-01
2 a 2011-01-01
5 a 2011-01-01
3 a 2010-01-01
After the second part it should look like this (so the first 3 after the row whose id is 1):
id |name |date
2 a 2011-01-01
5 a 2011-01-01
3 a 2010-01-01
I have no any idea how could I solve it, please help me.
EDIT:
This is the concrete code I'd like to re-write:
SELECT `id`, `questions`.`userid`, `categories`.`name`, `user`.`username`, `title`,
`details`, `date` FROM `questions`
LEFT JOIN `user`
ON `questions`.`userid` = `user`.`userid`
LEFT JOIN `categories`
ON `questions`.`categoryid` = `categories`.`categoryid`
ORDER BY `date` DESC LIMIT 10
SELECT *
FROM table
WHERE date < (SELECT date FROM table WHERE id = 1)
ORDER BY date DESC
LIMIT 3
This isn't pretty because MySQL doesn't support row_number() or common table expressions, but it should work. Basically, get the row number ordered by the date, then select those whose row number is greater than an arbitrary value (in this case 1). Finally use limit to select the number of records you want.
SELECT id, name, mydate
FROM (
SELECT id, name, mydate, #rn:=#rn+1 rn
FROM mytable, (select #rn:=0) t
ORDER BY mydate DESC
) t2
WHERE rn > (
select rn
from (
SELECT id, name, mydate, #rn:=#rn+1 rn
FROM mytable, (select #rn:=0) t
ORDER BY mydate DESC
) t2
where id = 1
)
LIMIT 3
SQL Fiddle Demo
This is what you want to do... if finds the first id thats equal to 4 and then selects those out. then limit the offset to go to the next row and pull out 3
SELECT id, name, m_date from(
SELECT id, name, m_date, #a := id, if(#a = 4, #b := 1, #b) AS join_id
FROM test
join(SELECT #a := 0, #b := 0) t
ORDER BY m_date DESC
) AS tt
WHERE join_id = 1
LIMIT 1,3
SELECT temp.`id`, temp.`userid`, `categories`.`name`, `user`.`username`, temp.`title`,
temp.`details`, temp.`date` FROM (
SELECT `id`, `categoryid`, `details`, `title`, `userid`, `date`, #a := id, if(#a = 11, #b := 1, #b) AS join_id
FROM `questions`
join(SELECT #a := 0, #b := 0) t
ORDER BY `date` DESC
) as temp
LEFT JOIN `user`
ON temp.`userid` = `user`.`userid`
LEFT JOIN `categories`
ON temp.`categoryid` = `categories`.`categoryid`
WHERE join_id = 1
LIMIT 1,10;
SEE FIDDLE for clarification

How to get three records based on agentID and rank in mysql

How to get the three records i.e his record,previous rank record and after rank record
I had SP in below fiddle:
DELIMITER $$
CREATE DEFINER=`ntc`#`%` PROCEDURE `stckrank`()
BEGIN
SELECT AgentID,
current_day_amount,
month_amount,
year_amount,
#Position:=#Position + 1 AS `Rank`
FROM
(
SELECT just_agent.AgentID,
total_current_date.Totoalamountperday AS current_day_amount,
total_current_month.Totoalamountpermonth AS month_amount,
total_year.Totoalamountperyear AS year_amount
FROM
(
SELECT DISTINCT AgentID
FROM collection
) just_agent
LEFT OUTER JOIN
(
select AgentID, SUM(AmountRecevied) as Totoalamountperday
from collection
where day(Date_Time) = day(CURRENT_DATE())
group by AgentID
) total_current_date
ON just_agent.AgentID = total_current_date.AgentID
LEFT OUTER JOIN
(
select AgentID, sum(AmountRecevied) as Totoalamountpermonth
from collection
where date_time between DATE_FORMAT(NOW(), '%Y-%m-01') and LAST_DAY(now() - interval 0 month)
group by AgentID
) total_current_month
ON just_agent.AgentID = total_current_month.AgentID
LEFT OUTER JOIN
(
select AgentID, sum(AmountRecevied) as Totoalamountperyear
from collection
where year(Date_Time) = YEAR(CURRENT_DATE())
group by AgentID
) total_year
ON just_agent.AgentID = total_year.AgentID
ORDER BY total_year.Totoalamountperyear DESC
) Sub1
CROSS JOIN (SELECT #Position:=0) Sub2;
END
output:
agentiid dayamount monthamount yearamount rank
2 3000 4000 7000 1
1 2000 3000 5000 2
3 200 300 500 3
4 100 100 200 4
now if i select agent id 2 i need to get below record and no record for above so null or 0 should show
select agent id -2
Need to show or get
his rank record and after record
agentiid dayamount monthamount yearamount rank
2 3000 4000 7000 1
1 2000 3000 5000 2
You can do it joining the table to itself on a rank condition:
SELECT t2.*
FROM yourTable t1
JOIN yourTable t2
ON ABS(t1.rank - t2.rank) <= 1.5 --is this what you want ?
WHERE t1.agentiid = 2
This SQL fiddle provides the desired results.
With this join, each row in your original table is associated to itself (always) and to the line with previous and next rank (if they exist).

SQL/MYSQL Update child under parent till null

i have a database table like this.
userID RefralID balance
1 0 0
2 1 0
3 2 0
4 3 0
5 8 0
now i want a MYSQL query to update the balance of each child under userID 1.
stuck there from 10 hours, but couldn't find desired Solution.
Results should like this if we update balance=balance + 10 where userID = '1'
as the 2,3,4 are child and grand child of '1' so their balance should be updated
userID RefralID balance
1 0 0
2 1 10
3 2 10
4 3 10
5 8 0
update tblA T2 join
(
SELECT
#r AS _id,
(SELECT #r := userid FROM tblA WHERE refralid = _id limit 1) AS userid,
#l := #l + 1 AS lvl
FROM
(SELECT #r := 1, #l := 0) vars,
tblA m
) T1
ON T1._id = T2.userid
set balance=balance+10
where T2.userid<>1
#r := 1
T2.userid<>1
The value 1 above is the userid=1
Could remove the #l (level) as that is for reference.
http://sqlfiddle.com/#!2/e606a/2
The general approach is :
create table temp1 (int id);
create table temp2 (int id);
insert into temp1 select ReferalID from your_table where userID = 1
while exists (select 1 from temp1)
begin
truncate table temp2
update your_table
set balance = balance + 10
where userID in (select * from temp1)
insert into temp2 select * from temp1
truncate table temp1
insert into temp1
select ReferalID
from your_table
where userID in (select * from temp2)
end