How to fetch the last row MySQL - mysql

I have 100k Data; this is all just my example
I have this 2 tables
I want to check into my table2 if the schedule exists in my table1.
If it exists the last schedule will be the output with remarks = 'OK' and Balance = '0'
my sample query:
select *
from table2 as A
join table1 as B ON A.ID = B.ID
where A.Remarks = 'OK'
and A.Schedule = (select max(schedule) from table1)
and A.balance = '0'
and B.Balance = 0
the output should be like this
ID
Schedule
BALANCE
Remarks
1
5
0
OK
TABLE1
ID
Schedule
BALANCE
Remarks
1
1
0
OK
1
2
0
OK
1
3
0
OK
1
4
0
OK
1
5
0
OK
2
6
100
NOT_OK
TABLE2
ID
Schedule
BALANCE
Remarks
1
1
0
OK
1
2
0
OK

Select A.ID,
max(B.Schedule),
A.Balance,
A.Remarks
from table2 as A
join table1 as B ON A.ID = B.ID
Where A.Remarks = 'OK'
and A.Balance = '0'
and B.Balance = 0
Group By A.ID,
A.Balance,
A.Remarks

Related

Updating table based on same table with a max value

Have a table data structure like below:
id
regid
docid
archived
1
1000
1
0
2
1000
2
0
3
1000
3
0
4
2000
1
0
5
2000
2
0
6
3000
1
0
7
3000
2
0
8
3000
3
0
9
3000
4
0
What I'm trying to do update the archived column to 1 where the docid is less than the max docid, by each regid group.
So I should end up with id's 3, 5 & 9 not being set to 1
Have tried:
update table t1
join (select max(docid) as maxdocid, regid from table) t2 on t1.docid < t2.maxdocid and t1.regid = t2.regid
set t1.archived = 1
But doesn't work, only does the first regid group.
Here's a solution (in MySQL 8.0+) using a CTE:
WITH numbered_table AS (
SELECT id, ROW_NUMBER() OVER (PARTITION BY regid ORDER BY docid DESC) AS rownum
FROM mytable
)
UPDATE mytable JOIN numbered_table USING (id)
SET archived = 1
WHERE rownum > 1
AND archived = 0;
Second solution, if you use an older version of MySQL that doesn't support CTE syntax:
You don't really need to compute the max docid value. If you want to update all rows except for the row with the max docid value, then you can check if a row can be matched to any other row with a greater docid value.
UPDATE mytable AS t1
INNER JOIN mytable AS t2 ON t1.regid = t2.regid AND t1.docid < t2.docid
SET t1.archived = 1
WHERE t1.archived = 0;
This will be true for all rows except the row with the max value. That row will be excluded automatically by the join.
In steps:
Create a query with the MAX value, per docid:
SELECT
ID,
regid,
docid,
(SELECT MAX(docid) FROM t1 te where te.regid=t.regid) as M
FROM t1 t
Join the result, and update:
UPDATE t1
JOIN (
SELECT
ID,
regid,
docid,
(SELECT MAX(docid) FROM t1 te where te.regid=t.regid) as M
FROM t1 t
) x ON t1.id=x.id
SET archived = 1
WHERE t1.docid<x.M AND t1.archived=0;
see: DBFIDDLE
You could try:
update test_tbl t1
set t1.archived = 1
where t1.archived = 0
and t1.id not in ( select t2.id
from (select max(id) as id,
regid,
max(docid)
from test_tbl
group by regid
) as t2
) ;
Result:
id regid docid archived
1 1000 1 1
2 1000 2 1
3 1000 3 0
4 2000 1 1
5 2000 2 0
6 3000 1 1
7 3000 2 1
8 3000 3 1
9 3000 4 0
Demo
Or you can use a LEFT JOIN
update test_tbl t1
left join ( select max(id) as id,
regid,
max(docid) as docid
from test_tbl
group by regid
) as t2 on t1.id=t2.id
set t1.archived = 1
where t1.archived = 0
and t2.id IS NULL
Demo
Use a self join in the update statement:
UPDATE tablename t1
INNER JOIN tablename t2
ON t2.regid = t1.regid AND t2.docid > t1.docid
SET t1.archived = 1;
See the demo.

MySQL: Join 3 tables with distinct values

So I have 3 tables: tableA, tableB, tableC with structures as follows
tableA
id
name
state
1
Ray
MD
2
Sam
LA
3
John
NY
tableB
id
a_id
amount
code
1
2
10
CHARGE
2
2
20
CHARGE
3
3
70
CHARGE
tableC
id
a_id
amount
code
1
2
50
CHARGE
2
2
40
DEPOSIT
3
1
60
CHARGE
I need the output of the join as follows:
A id
amount
1
60
2
30
3
70
So, here it calculates the sum of amount based on id in tableA. It checks the tableB for amount and if not present only then it checks tableC. Thats why the id 2 has amount 30 in output.
But what actually happens is the sum of both tables are added. So I get amount 120 for id 2. How do I get the required output?
So I tried this query here
Select if( SUM(CASE WHEN B.code != 'DEPOSIT'
THEN B.amount
ELSE 0 END) > 0,
SUM(CASE WHEN B.code != 'DEPOSIT'
THEN B.amount
ELSE 0 END),
SUM(CASE WHEN C.code != 'DEPOSIT'
THEN C.amount
ELSE 0 END)) as total
FROM tableA as A
left join tableB AS B on A.id=B.a_id
LEFT JOIN tableC AS C on A.id=C.a_id
GROUP BY A.id
You can try a solution like this
Select A.id, SUM(if(B.amount is NOT NULL,B.amount, C.amount)) as total
FROM tableA as A
LEFT JOIN tableB AS B on A.id=B.a_id and B.code != 'DEPOSIT'
LEFT JOIN tableC AS C on A.id=C.a_id and C.code != 'DEPOSIT'
GROUP BY A.id
Test this:
SELECT id, CASE WHEN b.amount
THEN b.amount
ELSE c.amount
END amount
FROM tableA a
LEFT JOIN ( SELECT a_id id,
SUM( CASE WHEN code != 'DEPOSIT'
THEN amount
ELSE 0
END ) amount
FROM tableB
GROUP BY id ) b USING (id)
LEFT JOIN ( SELECT a_id id,
SUM( CASE WHEN code != 'DEPOSIT'
THEN amount
ELSE 0
END ) amount
FROM tableC
GROUP BY id ) c USING (id)

Two where condition for same column using group by

I am having two tables, t1, t2. My tables and expected result are given below.
My table schema is in sqlfiddle
t1:
id branch_name
1 branch1
2 branch2
3 branch3
4 branch4
5 branch5
t2:
id VBRNCH VTOBRN vqty
1 1 0 10
2 2 0 20
3 3 0 30
4 0 4 40
5 0 5 50
Expected Result is:
branch_name send received
1 10 0
2 20 0
3 30 0
4 0 40
5 0 50
What i have tried is:
SELECT
b1.branch_name,
i1.vqty AS send,
i2.vqty AS received
FROM t2 i1
INNER
JOIN t1 b1
ON b1.id = i1.VBRNCH
INNER JOIN t2 i2
ON b1.id = i2.VTOBRN
GROUP
BY i1.VTOBRN,
i2.VBRNCH;
But I am getting zero rows.
I think this is the query you are looking for:
SELECT t1.branch_name,
COALESCE(SUM(send.vqty), 0) AS send,
COALESCE(SUM(receive.vqty), 0) AS received
FROM t1
LEFT JOIN t2 AS send on t1.id = send.VBRNCH
LEFT JOIN t2 AS receive on t1.id = receive.VTOBRN
GROUP BY t1.branch_name
Demo here
E.g.
SELECT x.*
, COALESCE(sent,0) sent
, COALESCE(received,0) received
FROM t1 x
LEFT
JOIN
( SELECT from_br
, SUM(vqty) sent
FROM t2
GROUP
BY from_br
) a
ON a.from_br = x.id
LEFT
JOIN
( SELECT to_br
, SUM(vqty) received
FROM t2
GROUP
BY to_br
) b
ON b.to_br = x.id
ORDER
BY id;
http://sqlfiddle.com/#!9/af0973/21

How to split a row into 2 based on an if condition

I am struck with following process. I have two tables named table1 & table2.
table1 consists total amount with current status. table2 consists filled amount.
I want to get the result like, if the table1.status = 'cancel' then I need to get 2 rows as showed in expected result. Is there any way to do that?
table1
unq_id | amount | status | type
1 4 'cancel' 'two'
2 2 'done' 'one'
table2
p_id | unq_id | filled
1 1 1
2 2 2
My query
SELECT
a.unq_id as id_val,
(IFNULL(b.filled,0)) as filled
FROM
table1 AS a
LEFT JOIN table2 AS b
ON a.unq_id = b.unq_id
WHERE
(a.status = "done"
OR a.status = "cancel")
current result
id_val | filled
1 1
2 2
expected result
id_val filled
1 3 (cancelled amount [ 4 - filled amount])
1 1 (filled amount)
2 2
you can use a query like below
SELECT
a.unq_id as id_val,
ABS(opt-IFNULL(b.filled,0)) as filled
FROM
(select *, 0 as opt from table1
union all
select *,4 as opt from table1 where status = "cancel")AS a
LEFT JOIN table2 AS b
ON a.unq_id = b.unq_id
WHERE
(a.status = "done"
OR a.status = "cancel")
You can use Union...
First part of query you already have, giving you part of your result. You just need to add second query to it to fetch rest of the result:
SELECT a.unq_id as id_val,(ISNULL(b.filled,0)) as filled FROM
Tab1 AS a LEFT JOIN Tab2 AS b ON a.unq_id = b.unq_id
WHERE (a.status = "done" OR a.status = "cancel")
UNION
SELECT a.unq_id as id_val, a.amount - b.filled as filled FROM
Tab1 AS a LEFT JOIN Tab2 AS b ON a.unq_id = b.unq_id
WHERE (a.status = 'cancel')
ORDER BY id_val

Mysql Update Query for sample table

I have 1 table called sample and it has 3 columns.
id customer default_address
1 1 0
2 1 0
3 1 0
4 1 0
5 2 0
6 2 0
7 3 0
8 3 0
9 2 0
10 2 0
Here I want to group by customer and update first default address should be 1 and rest all for 0 for every customer. How to do it mysql query?
Thanks
UPDATE tb a
LEFT JOIN
(
SELECT customer, MIN(id) id
FROM tb
GROUP BY customer
) b ON a.customer = b.customer AND
a.ID = b.ID
SET a.default_address = b.ID IS NOT NULL
SQLFiddle Demo
UPDATE sample
LEFT JOIN
(SELECT MIN(id) id,customer
FROM sample
GROUP BY customer) t ON sample.customer=t.customer
SET default_address="1"
WHERE sample.id=t.id;
This should work.
Update Table1
INNER JOIN (Select Min(`id`) as MinID,`customer`
From Table1 Group by `customer`) t2
SET Table1.`default_address` = 1
WHERE Table1.`id` = t2.MinID;
SAMPLE FIDDLE