I have 2 tables that I need to join via ID without getting the duplicate values For ID, InfoA, and InfoB. I do not need the data in column InfoB2. When I join the table on ID because it is a 1 to many join I end up with duplicate values and want to get rid of those. I only want ID, InfoA, and InfoB without the duplicates. Any ideas?
Example:
TableA:
| ID | InfoA |
| 1 | animals|
| 2 | plants |
TableB:
| ID | InfoB | InfoB2 |
| 1 | A | X |
| 1 | A | Y |
| 1 | A | Z |
| 2 | B | X |
| 2 | B | Y |
| 2 | B | Z |
Doing a normal join, because it is 1 to many I get this but do not want the duplicates. I don't want this:
| ID | InfoB | InfoB |
| 1 | animals| A |
| 1 | animals| A |
| 1 | animals| A |
| 2 | plants | B |
| 2 | plants | B |
| 2 | plants | B |
My goal is to get this (note I do not need column InfoB2):
| ID | InfoA | InfoB |
| 1 | animals| A |
| 2 | plants | B |
You could use the distinct keyword:
SELECT DISTINCT a.id, infoa, infob
FROM tablea a
JOIN tableb b ON a.id = b.id
The fastest way is likely to be:
select a.*,
(select b.infob from tableb b on a.id = b.id limit 1)
from tablea a;
For performance, you would want an index on tableb(id, infob).
Related
I have two tables in a MySQL database -
table_a:
+----+---------+-------------+-----------------
| id | section | sub_section | ...other_fields
+----+---------+-------------+-----------------
| 1 | A | X |
| 2 | A | Y |
| 3 | A | Z |
| 4 | B | P |
| 5 | B | Q |
| 6 | C | L |
| 7 | C | M |
| 8 | C | N |
| 9 | C | O |
+----+---------+-------------+-----------------
table_b:
+----+-------------+---------+-----------------
| id | sub_section | b_count | ...other_fields
+----+-------------+---------+-----------------
| 1 | X | 1 |
| 2 | Y | 1 |
| 3 | L | 0 |
| 4 | P | 1 |
| 5 | P | 1 |
| 6 | X | 0 |
| 7 | M | 1 |
| 8 | Y | 0 |
| 9 | Q | 1 |
+----+-------------+---------+-----------------
I want to find the count of sub_section in table_b and the sum of b_count from Table B for each distinct section in table_a -
Expected Result:
+---------+--------------------+--------------+
| section | COUNT(sub_section) | SUM(b_count) |
+---------+--------------------+--------------+
| A | 4 | 2 |
| B | 3 | 3 |
| C | 2 | 1 |
+---------+--------------------+--------------+
One way to do this would be to run Count(section) number of queries and then combine the results.
Something like:
SELECT 'A' AS section, COUNT(sub_section), SUM(b_count) FROM table_b WHERE sub_section IN (SELECT DISTINCT sub_section FROM table_a WHERE section='A')
UNION
SELECT 'B' AS section, COUNT(sub_section), SUM(b_count) FROM table_b WHERE sub_section IN (SELECT DISTINCT sub_section FROM table_a WHERE section='B')
UNION
SELECT 'C' AS section, COUNT(sub_section), SUM(b_count) FROM table_b WHERE sub_section IN (SELECT DISTINCT sub_section FROM table_a WHERE section='C');
Is there a better way to do this in a query?
The section list in table_a is dynamic and might change and I do not want to update my query each time the values change.
SELECT t1.section, COUNT(DISTINCT t1.sub_section), SUM(t2.b_count)
FROM table_a t1
LEFT JOIN table_b t2 USING (sub_section)
GROUP BY t1.section;
fiddle
I have two MySQL tables (table_a and table_b) and a join table (table_c).
Table Structures:
table_a:
__________________
| table_a: |
|----------------|
| id |
| result_column |
------------------
table_b:
__________________
| table_b: |
|----------------|
| id |
| name |
------------------
table_c:
__________________
| table_c: |
|----------------|
| id |
| table_a_id |
| table_b_id |
------------------
My Goal:
I want to find a query that will:
Iterate over every table_a record and get the table_a.id value
Find any records in table_c which have a matching table_c.table_a_id value
For each matching record in table_c get the table_c.table_b_id value
Find the record in table_b which has a matching table_b.id value
For that matching record in table_b get the table_b.name value
In table_a, concatenate each matched name value into the corresponding table_a.result_column
Example:
Before the Query:
_______________________ _________________________________ ________________
| table_a: | | table_c: | | table_b: |
|---------------------| |-------------------------------| |--------------|
| id | result_column | | id | table_a_id | table_b_id | | id | name |
|-----|---------------| |-----|------------|------------| |-----|--------|
| 1 | | | 1 | 1 | 3 | | 1 | Kevin |
| 2 | | | 2 | 1 | 4 | | 2 | Jesse |
| 3 | | | 3 | 2 | 2 | | 3 | Karen |
----------------------- | 4 | 3 | 1 | | 4 | Tim |
| 5 | 3 | 5 | | 5 | Lauren |
--------------------------------- ----------------
After the Query:
_______________________ _________________________________ ________________
| table_a: | | table_c: | | table_b: |
|---------------------| |-------------------------------| |--------------|
| id | result_column | | id | table_a_id | table_b_id | | id | name |
|-----|---------------| |-----|------------|------------| |-----|--------|
| 1 | Karen, Tim | | 1 | 1 | 3 | | 1 | Kevin |
| 2 | Jesse | | 2 | 1 | 4 | | 2 | Jesse |
| 3 | Kevin, Lauren | | 3 | 2 | 2 | | 3 | Karen |
----------------------- | 4 | 3 | 1 | | 4 | Tim |
| 5 | 3 | 5 | | 5 | Lauren |
--------------------------------- ----------------
For absolute clarity, I understand that this is incredibly bad practice within a relational data-table. This is as far from normalization as one can get. I would never design a database like this. I was tasked with creating a custom column with a list of values purely for a business case.
The query you seem to want is:
select c.table_a_id, group_concat(b.name separator ', ')
from c join
b
on c.table_b_id = b.id
group by c.table_a_id;
If you actually want to update a, you can put this into an update statement:
update a join
(select c.table_a_id, group_concat(b.name separator ', ') as names
from c join
b
on c.table_b_id = b.id
group by c.table_a_id
) cb
on cb.table_a_id = a.id
set result_column = cb.names
Previous answer is close; but you also required that you only want the records matched in table C that are in A.
The first query does not meet this requirement; but the update statement does, as it will only update records in table A, if the id matches the table_a_id value pulled from table C.
Given what you said you wished for the end result, the update statement above would work.
If you wish to be explicit in your logic, just add a join from table A to table C.
select a.id, group_concat(b.name separator ', ')
from a
join c ON (a.id = c.table_a_id)
join b ON (c.table_b_id = b.id)
group by a.id;
I have the following situation:
tableA
+-------+-------+
| id | Value |
+-------+-------+
| 1 | 1000 |
| 2 | 20 |
| 3 | 62 |
| 4 | 0 |
+-------+-------+
tableB
+-------+--------+
| Value | Lookup |
+-------+--------+
| 10 | a |
| 20 | b |
| 30 | b |
| 40 | g |
| 50 | h |
| 60 | f |
| 70 | a |
| 80 | a |
| 90 | v |
| 100 | b |
+-------+--------+
And I need to return the lookup in table B that most closely matches the value field in table A. For example.
+-------+-------+--------+
| id | Value | Lookup |
+-------+-------+--------+
| 1 | 1000 | b |
| 2 | 20 | b |
| 3 | 62 | f |
| 4 | 0 | a |
+-------+-------+--------+
How can I go about doing this?
Here is an option using joins:
SELECT
a.Id, a.Value, b.Lookup
FROM tableA a
CROSS JOIN tableB b
INNER JOIN
(
SELECT a.Id, MIN(ABS(a.Value - b.Value)) AS min_abs_value
FROM tableA a
CROSS JOIN tableB b
GROUP BY a.Id
) t
ON a.Id = t.Id AND
ABS(a.Value - b.Value) = t.min_abs_value;
Demo
While this query does join to a subquery, the subquery is not correlated.
One way is to use a correlated subquery:
SELECT a.Id, a.Value,
(SELECT b.Lookup
FROM TableB AS b
ORDER BY ABS(a.Value - b.Value) LIMIT 1)
FROM TableA AS a
Demo here
I was having problems in creating counting rows by grouping based on a given field value.
For example: I have a Table A structure like this:
+------+------------+
| id | Person |
+------+------------+
| 1 | "Sandy" |
| 2 | "Piper" |
| 3 | "Candy" |
| 4 | "Pendy" |
+------------+------+
Also I have a Table B structure like this:
+------+------------+---------+
| id | Person | Point |
+------+------------+---------+
| 1 | "Sandy" | 10 |
| 2 | "Piper" | 20 |
| 3 | "Candy" | 30 |
| 4 | "Sandy" | 10 |
| 5 | "Piper" | 20 |
| 6 | "Zafar" | 30 |
+------------+------+---------+
And needed a result like:
+------+------------+---------+
| id | Person | Point |
+------+------------+---------+
| 1 | "Piper" | 40 |
| 2 | "Candy" | 30 |
| 3 | "Zafar" | 30 |
| 4 | "Sandy" | 20 |
| 5 | "Pendy" | 0 |
+------------+------+---------+
I hope the table examples are itself self-explanatory.
SELECT person
, SUM(point) total
FROM
( SELECT person,point FROM table_b
UNION
ALL
SELECT person,0 FROM table_a
) x
GROUP
BY person
ORDER
BY total DESC;
It is a simple left join with a group by
select tableA.person, sum(tableB.points) from tableA left join tableB on tableA.person = tableB.person group by tableA.person
union
select tableB.person, sum(tableB.points) from tableB left join tableA on tableA.person = tableB.person where tableA.id is null group by tableA.person
I think below sql useful to you.
select a.id, a.Person,b.total_point from (
select id, Person from tablea) as a join
(select Person, sum(Point) as total_point from tableb group by person) as b on a.person =b.person
Thank you
I have a somewhat complicated mySQL query I want to run, and I am having trouble thinking of how to write it.
Basically I have three tables:
a(aid, name);
b(bid, val);
ab(aid, bid)
What I want to do is create a query that creates a table like this:
c(aid, valSum);
I want valSum to start at 0 and add the value of bid.val of every relation between aid and bid.
For example:
a:
+-----+------+
| aid | name |
+-----+------+
| 1 | Joe |
| 2 | Jon |
| 3 | Max |
+-----+------+
b:
+-----+-----+
| bid | val |
+-----+-----+
| 1 | 2 |
| 2 | 4 |
| 3 | 6 |
+-----+-----+
ab:
+-----+-----+
| aid | bid |
+-----+-----+
| 1 | 1 |
| 1 | 2 |
| 2 | 2 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
+-----+-----+
c:
+-----+--------+
| aid | valSum |
+-----+--------+
| 1 | 6 |
| 2 | 10 |
| 3 | 12 |
+-----+--------+
Something like below:
SELECT a.aid, SUM(b.val) AS valSum
FROM a
INNER JOIN ab ON a.aid = ab.aid
INNER JOIN b ON ab.bid = b.bid
GROUP BY a.aid
You don't need to join to table a at all:
SELECT ab.aid, sum(b.val) AS valSum
FROM ab
JOIN b USING (bid)
GROUP BY 1;
... except to list rows from a without any match in ab. You would have to use LEFT JOIN in this case, though:
SELECT a.aid, sum(b.val) AS valSum
FROM a
LEFT JOIN ab USING (aid)
LEFT JOIN b USING (bid);
GROUP BY 1;
valSum would be NULL for those rows.