Joining tables and getting a count of specific record - mysql

I am having two tables say table_a and table_b with following structure.
table_a : ID(primary key), value_one
table_b: ID, value_two
Note that id in table_b is not primary and contains multiple records to same id.
now i want a third table which displays a record for every id in table_a with columns being
id column_count
the column _count will display number of records (count) in table_b with value_two = 'c'. and i want to iterate this to all records of table_a.
For example lets say our table_a is like this:
id value_one
1 20
2 40
3 50
table_b
id value_two
1 10
1 20
1 10
2 40
2 10
3 40
3 10
I want records with value_two = 10 so my new table would look like
id count
1 2
2 1
3 1
Since id 1 has two records with value_two = 10 and id 2 and id 3 have one record each with value_two = 10

One way of doing this uses a correlated subquery:
select a.id,
(select count(*) from table_b b where b.id = a.id and b.value_two = 10) as cnt_10
from table_a a;
Another method uses a left join:
select a.id, count(b.id)
from table_a a left join
table_b b
on b.id = a.id and b.value_two = 10
group by a.id;
In your example data, this works:
select b.id, count(*)
from table_b b
where b.value_two = 10
group by b.id;
This is equivalent under the following circumstances:
All ids in a are in b.
All ids have at least one value of 10.
If these two conditions are true, then use this simpler query.

You can do conditional aggregation :
select id, sum(value_two = 10) as count
from table_b tb
group by id;
If you want matching ids then add INNER JOIN. This will show 0 count whereas value_two = 10 not found. You can add where clause to find only value_two = 10 count.

Related

Update value of one table with summed value of related table by using intermediate table

I have three tables A, A_B and B.
Since mySQL doesn't support many to many relationships, tables A and B are related to each other by intermediate table A_B.
Table A: Table A_B: Table B:
aId aCount aId bId bId bCo
1 10 1 1 1 4
2 15 1 2 2 5
3 20 2 1 3 6
3 2 4 7
3 4
Now I want to add bCount of each bId to each related aCount.
Desired result:
Table A: Remark:
aId aCount (Current aCount + all related bCounts)
1 19 (10 + 4 + 5)
2 19 (15 + 4)
3 32 (20 + 5 + 7)
My mySQL knowledge is too basic.
I can create a SELECT query which gives me a result table like i want table A to look like after update, but I can't create the update statement. Everything I tried led to syntax errors or undesired results.
I also had one statement which might had work, but it took way to long to execute. Now I'm just confused about what to do.
Desired Result looks like:
SELECT `aId`, aCount + SUM(`bCount`) as `aCount` from `A`
INNER JOIN `A_B` ON `A_B`.`aId` = `A`.`aId`
INNER JOIN `B` ON `B`.`bId` = `A_B`.`bId`
GROUP BY `aId`;
Is an update like I want even possible with a single query or do I need multiple (performance wise)?
Can anyone help me out with an approach or with creating statements?
Try below: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=0b6a287d41eed001710e94612c4228ba
select x.id,x.val,sum(tableb.val)+x.val as vals from
(select * from tablea inner join tableab on tablea.id=tableab.id1) x inner join
tableb on x.id2=tableb.id
group by x.id,x.val,id1
Output:
id val vals
1 10 19
2 15 19
3 20 32
To update tablea:
UPDATE tablea INNER JOIN
(SELECT x.id, x.val, SUM(tableb.val) + x.val as vals FROM
(SELECT * FROM tablea INNER JOIN tableab ON tablea.id = tableab.id1) x INNER JOIN
tableb ON x.id2 = tableb.id
GROUP BY x.id, x.val, id1)Z ON tablea.id=Z.id
SET tablea.val = Z.vals;

Fetch only those records from table join which has not reached its final state

if have two tables A and B:
Table A
id work_name
1 10001
2 10002
and
Table B
id work_id final_status
1 1 0
2 2 0
3 1 1
i have to fetch only those work_id whose final status is not 1
In Above Table output should 2 as final_status of work_id 1 is reached to 1.
I have tried the Query but it is not giving me desired result
My Query:
select B.work_id from A inner join B on A.id = B.work_id where final_status!=1
My Result:
1
2
I want to exclude 1 as it has reach to its final status.
There are multiple ways to produce the required output:
join table B twice on table A
join table B once, get the max() of final_status and filter in having clause
combination of in() and not in() subqueries
combination of exists() and not exists() subqueries
I prefer the last method because exists() / not exists() do not have to actually fetch the data from table B:
select A.*
from A
where exists(select 1 from B where B.work_id=A.id and B.final_status=0)
and not exists(select 1 from B where B.work_id=A.id and B.final_status=1)

How to use limit and group by together in mysql

With these sample tables
table_a table_b
column_1 column_1 column_2
1 1 A
2 1 B
3 2 C
4 3 D
5 4 E
the query below
SELECT table_a.column1,table_b.column2
FROM table_a
INNER JOIN table_b ON table_a.column1 = table_b.column_1
GROUP BY table_a.column1 LIMIT 3
gives only 2 results (limit is 3) since the value 1 is duplicating in table_b. How can i get 3 results with unique table_a.column1 values. In general how can i use group by and limit together with group by having no impact on the limit
After minor adjustments with columns names (changing column1 into column_1 and column2 into column_2) your query gives me exactly 3 rows of results.
1 A
2 C
3 D

How to fetch matched data from first table and unmatched from second table

I have 2 tables with same structure
eg. Table A and B with columns id,value.
Table A
ID VALUE
1 10
2 20
3 0
Table B
ID VALUE
1 24
2 26
3 0
4 40
5 50
expected output:
ID VALUE
1 10
2 20
3 0
4 40
5 50
as per output first three id is matched with table B so id(1,2,3) with value comes from table A and id(4,5) with value is not matched so it comes from table B.
You could use a right join on table b (or a left join on table a) and use a coalesce operator.
select b.id, coalesce(a.value, b.value)
from tablea a
right join tableb b on a.id = b.id
or
select b.id, coalesce(a.value, b.value)
from tableb b
left join tablea a on a.id = b.id
see SqlFiddle

Combine queries in MySQL

I have two table in MySQL that looks as follows:
ID Name Information
1 A fsdf
2 B ada
3 A dsafd
4 A retret
5 C asdfsa
6 B xzc
and,
P_ID Name Loc_X Loc_Y
1 A 2 3
2 B 3 4
3 C 4 5
I would like to run a query in MySQL that return the result as follows:
NAME COUNT Loc_X Loc_Y
A 3 2 3
B 2 3 4
C 1 4 5
Currently, I am able to execute the following query:
SELECT Name,COUNT(*) as count FROM Table_A GROUP BY Name ORDER BY count DESC;
to get the following result:
NAME COUNT
A 3
B 2
C 1
I know that probably I can use this result to extract only the "Name" and fire another query to get the Loc_X and Loc_Y using PHP, but I was wondering whether there is a moe efficient way of doing it using DML. Is there a way to nest the queries?
Try something like this :
SELECT Table_A.Name,COUNT(*) as count, Table_B.Loc_X, Table_B.Loc_Y
FROM Table_A
INNER JOIN Table_B ON Table_A.name = Table_B.name
GROUP BY Table_A.Name, Table_B.Loc_X, Table_B.Loc_Y
ORDER BY count DESC;
I think you just need to join the tables on the common field here.
Try:
SELECT a.Name, count(a.id) AS Count b.Loc_X, b.Loc_Y
FROM Table_A a
INNER JOIN Table_B b ON a.Name = b.Name
GROUP BY a.Name