Select according to rows increments - mysql

I have a MySQL database like this one :
ID | Twin | Tloss
0 | 300 | 250 #first entry
1 | 301 | 250 #win; score 1 - 0
2 | 302 | 250 #win; score 2 - 0
3 | 302 | 251 #lose: score 2 - 1
4 | 303 | 251 #win; score 3 - 1
5 | 304 | 251 #end of match1 : Win 4 - 1
6 | 304 | 252 #lose; score 0 - 1
7 | 304 | 253 #lose; score 0 - 2
8 | 304 | 254 #lose; score 0 - 3
9 | 304 | 255 #end of match2 : Lose 0 - 4
10 | 304 | 256 #lose; score 0 - 1
11 | 305 | 253 #win; score 1 - 1
12 | 306 | 254 #win; score 2 - 1
13 | 306 | 255 #lose; score 2 - 2
14 | 307 | 255 #win; score 3 - 2
15 | 307 | 256 #end of match3 : Draw 3 - 3
....
I want to select all the ID corresponding to the match number "n",
considering a match is ended as soon as he wins 4 times or loses 4 times, draw is possible as the maximum number of round per match is 6.
I use SQL a lot since 1 months but I'm really lost on this one.
Could someone help me ?
Thanking you in advance,

I am assuming that some of the data above is broken (records 11-15, field tloss; record 5 should be Win 4 - 1). I also don't know what are the numbers 300 and 250 and how they change in the table. With these assumptions, this untested SQL might be want you want:
(revised after feedback from GordonLinoff)
SELECT #matchno := #matchno + 1 AS matchno
FROM (SELECT #matchno := 0) mn,
(SELECT ID, Twin, Tloss,
IF((Twin - #twin) = 4
OR (Tloss - #tloss) = 4
OR ((Twin - #twin) = 3 AND (Tloss - #tloss) = 3),
#twin := Twin AND #tloss := Tloss,
0)
FROM matches, (SELECT #twin := 300, #tloss := 250) AS base
WHERE (Twin - #twin) = 4
OR (Tloss - #tloss) = 4
OR ((Twin - #twin) = 3 AND (Tloss - #tloss) = 3)
ORDER BY ID
) endmatches

Related

Sorting issue with limit and offset MYSQL

I am facing sorting issue in mysql
See the output of below query:
select astrologers.id,astrologers.name,chat_online,online,experience from `astrologers`
where `astrologers`.`status` = '1'
order by experience asc limit 10;
id
name
chat_online
online
experience
15
Astro Anoop
0
0
3
20
Test Astro2
0
0
3
3
Test anoop
0
0
5
4
Anoop Kumar trivedi
0
0
5
7
Test
0
0
5
58
Neeraj yadav
1
0
5
45
Satish Kumar Gupta
1
1
10
56
AP Sharma
1
0
15
40
VG Astrologer App
1
0
55
In above result id 58 (Neeraj yadav) is at 6th position but when I run the same query with limit 3, same id 58 (Neeraj yadav) is at 3rd position:
select astrologers.id,astrologers.name,chat_online,online,experience
from `astrologers`
where `astrologers`.`status` = '1'
order by experience asc limit 3;
id
name
chat_online
online
experience
20
Test Astro2
0
0
3
15
Astro Anoop
0
0
3
58
Neeraj yadav
1
0
5
The 3rd row in above result should be id 3 (Test anoop) but it gives id 58 (Neeraj yadav)
Is this bug in mysql?
Is this a bug in MySQL?
No. The problem is that your sort is not deterministic, and gives ties in the third position:
| 3 | Test anoop | 0 | 0 | 5 |
| 4 | Anoop Kumar trivedi | 0 | 0 | 5 |
| 7 | Test | 0 | 0 | 5 |
| 58 | Neeraj yadav | 1 | 0 | 5 |
All 4 users have the same experience, hence leaving the database to figure out how they should be sorted.
When asked to return to top 3 rows, the database picks the first two, and then one of the 4 ties. The result that you get might not be consistent over consequent executions of the same query, as you are starting to see.
Bottom line: know you data; if you want a deterministic result, then use a deterministic sort. We could, for example, use id to break the ties, hence making the result predictable:
order by experience, id limit 3

Adding Amt1 and Amt2 values to the output column value of previous record

Input:
dated amount Amt1 Amt2
1/1/2017 100 0 10
1/2/2017 100 10 0
1/4/2017 100 0 0
1/6/2017 100 300 10
1/10/2017 100 0 20
1/11/2017 100 350 650
1/12/2017 100 0 234
Output:
dated amount Amt1 Amt2 Output Column
1/1/2017 100 0 10 100
1/2/2017 100 10 0 110
1/4/2017 100 0 0 120
1/6/2017 100 300 10 120
1/10/2017 100 0 20 430
1/11/2017 100 350 650 450
1/12/2017 100 0 234 1450
Output column is calculated with adding Amt1 and Amt2 values to the Output Column value of previous record.
Example: Output Column of
first record is as it is of Amount column,
second record will get from first record value of output column and Amt1 and Amt2 of first record i.e 100+0+10=110,
third record is from 110+10+0=120
fourth record is from 120+0+0=120
fifth record is from 120+300+10=430 ...
There are lots of examples of how to calculate running totals on this site and here's one which uses a variable. I am concerned that the purpose of the amount column is not defined but this solution works with the data provided for installation with mysql lower than version 8 (it will work with version 8 or above but there are better ways of doing it there). #tcadidot0 no hard coding required.
drop table if exists t;
create table t
( dated date, amount int, Amt1 int, Amt2 int);
insert into t values
(str_to_date('1/1/2017','%d/%m/%Y') , 100 , 0 , 10),
(str_to_date('1/2/2017','%d/%m/%Y') , 100 , 10 , 0),
(str_to_date('1/4/2017','%d/%m/%Y') , 100 , 0 , 0),
(str_to_date('1/6/2017','%d/%m/%Y') , 100 , 300 , 10),
(str_to_date('1/10/2017','%d/%m/%Y') , 100 , 0 , 20),
(str_to_date('1/11/2017','%d/%m/%Y') , 100 , 350 , 650),
(str_to_date('1/12/2017','%d/%m/%Y') , 100 , 0 , 234);
select t.dated,t.amount,t.amt1,t.amt2,
if(t.dated = (select min(t1.dated) from t t1),#op:=amount,
#op:=#op +
(select amt1 + amt2 from t t1 where t1.dated < t.dated order by t1.dated desc limit 1)
) op
from t
cross join (select #op:=0) o
order by dated;
+------------+--------+------+------+------+
| dated | amount | amt1 | amt2 | op |
+------------+--------+------+------+------+
| 2017-01-01 | 100 | 0 | 10 | 100 |
| 2017-02-01 | 100 | 10 | 0 | 110 |
| 2017-04-01 | 100 | 0 | 0 | 120 |
| 2017-06-01 | 100 | 300 | 10 | 120 |
| 2017-10-01 | 100 | 0 | 20 | 430 |
| 2017-11-01 | 100 | 350 | 650 | 450 |
| 2017-12-01 | 100 | 0 | 234 | 1450 |
+------------+--------+------+------+------+
7 rows in set (0.00 sec)

how create a ' one to many ' sql query statement

i have a table called(center_info) which which has a student's information and their total bills paid and total balance remained. and another table called (center_payments) which has records of each single date of bill paid by a student.
I want to join records of a student in table 1(center_info), to every date he paid a bill in table 2(center_payments)
below are the records in center_info:
id | student | term | bill | total_paid | total_balance | last_date_of_pymt |
---+---------+------+------+------------+---------------+-------------------+
5 mary 1 400 200 -200 6 / june / 2019
6 john 1 500 300 -200 2 / june / 2019
7 grace 2 450 400 -50 17 / august / 2019
8 mike 2 450 100 -350 15 / august / 2019
and the below are the different dates of payments in center_payments:
id | student | paid | balance | date | term |
---+---------+------+---------+--------------+------+
5 mary 100 -300 3 / june /2019 1
5 mary 100 -200 6 / june /2019 1
6 john 150 -350 1 / june /2019 1
6 john 150 -200 2 / june /2019 1
7 grace 400 -50 17 / aug /2019 2
8 mike 50 -400 5 / aug /2019 2
8 mike 50 -350 5 / aug /2019 2
I want to join records of students in table 1 and all their individual payments in table 2 where term(column)=1
currently am only able to print out a selected student and view all his records from the two tables with this code :
int row = c_FirstTerm.getSelectedRow();
try{
String table_click=(c_FirstTerm.getModel().getValueAt(row,0).toString());
String sgl="select center_info.id,center_info.student,center_info.bill,center_info.Term,center_info.total_paid,center_info.total_balance,center_info.last_date_of_pymt,center_payments.paid,center_payments.balance,center_payments.date from center_info INNER JOIN center_payments on center_info.term=center_payments.term and center_info.id=center_payments.id and center_info.Student='"+table_click+"'";
}catch(Exception e){
JOptionPane.showMessageDialog(null,e);
}
but assuming I don't select a particular student, how do I create a one-to-many relationship for students and their individual payments from both tables where term=1. eg like this:
//first group
id | student | paid | balance | date | term |
---+---------+------+---------+--------------+------+
5 mary 100 -300 3 / june /2019 1
5 mary 100 -200 6 / june /2019 1
id | student | term | bill | total_paid | total_balance | last_date_of_pymt |
---+---------+------+------+------------+---------------+-------------------+
5 mary 1 400 200 -200 6 / june / 2019
_____________________________________________________________________________
//next group
id | student | paid | balance | date | term |
---+---------+------+---------+--------------+------+
6 john 150 -350 1 / june /2019 1
6 john 150 -200 2 / june /2019 1
id | student | term | bill | total_paid | total_balance | last_date_of_pymt |
---+---------+------+------+------------+---------------+-------------------+
6 john 1 500 300 -200 2 / june / 2019

How to update the same row with condition in MySql?

Here's data
KeyID | Queue | Pay
65 1 0
60 2 0
58 3 1
57 4 1
55 5 0
54 6 0
53 7 1
50 8 1
if the data like this , I need a single MySql query to update it to be like below data table which update only Queue column.
KeyID | Queue | Pay
65 0 0
60 0 0
58 1 1
57 2 1
55 0 0
54 0 0
53 3 1
50 4 1
I have try this
update tabl1
set Queue = case when Pay = 0 then Queue=Queue-1 else Queue
But Queue number not look like this.
Please suggest.
Thank you in advance
We can try joining to a subquery which computes the sequence:
UPDATE yourTable k1
INNER JOIN
(
SELECT KeyID, rn
FROM
(
SELECT t1.KeyID,
(SELECT SUM(t2.Pay = 1) FROM yourTable t2
WHERE t2.KeyID >= t1.KeyID) rn
FROM yourTable t1
) t
) k2
ON k1.KeyID = k2.KeyID
SET
Queue = CASE WHEN Pay = 0 THEN 0 ELSE k2.rn END;
To see how the above logic is working, here is what the intermediate join table looks like:
KeyID | Queue | Pay | rn
65 | 1 | 0 | 0
60 | 2 | 0 | 0
58 | 3 | 1 | 1
57 | 4 | 1 | 2
55 | 5 | 0 | 2
54 | 6 | 0 | 2
53 | 7 | 1 | 3
50 | 8 | 1 | 4
That is, the innermost correlated subquery generates the queue sequence by counting the number of times Pay is 1.
Note that if you are using MySQL 8+, then there is a much simpler query using analytic functions:
UPDATE yourTable
SET Queue = CASE WHEN Pay = 0
THEN 0
ELSE SUM(Pay = 1) OVER (ORDER BY KeyID DESC) END;

mysql cumulative sum of same field value

I have sample data with table name catdog
| No | id | data |
1 1 4000
2 2 300
3 3 100
4 1 400
5 2 30
6 3 10
7 1 40
8 2 3
9 3 1
I want the result like this:
| No | id | data | totaldata |
1 1 4000 4000
2 2 300 300
3 3 100 100
4 1 400 4400 --------> 4000 + 400 on id
5 2 30 330 --------> 300 + 30 on id
6 3 10 110 --------> 100 + 10 on id
7 1 40 4440 --------> 4000 + 400 + 40 on id
8 2 3 333 --------> 300 + 30 + 1 on id
9 3 1 111 --------> 100 + 10 + 1 on id
Sum if field No is same.
How to write a mysql query for my case?
very very thank you so much GurV
Try this:
select no, id, data, c_data from (
select t1.*,
#data := case when #id = id then #data + data else data end c_data,
#id := id
from
(select * from catdog
order by id, No) t1
cross join (select #id := -1, #data := 0) t2) t
order by no;
It uses user defined variables to keep track of sum till now for each id