Given are two tables with with a common id and integer values:
table1: table2:
| id | val | | id | val |
+------+------+ +------+------+
| 1 | 0 | | 1 | 1 |
| 2 | 1 | | 1 | 1 |
| 3 | 1 | | 2 | 2 |
| 4 | 2 | | 2 | 2 |
| 5 | 2 | | 3 | 2 |
| 3 | 2 |
| 3 | 2 |
| 4 | 6 | <id shifted for readability>
How to archive this result in one query:
result-table:
| id | val |
+------+------+
| 1 | 2 |
| 2 | 5 |
| 3 | 7 |
| 4 | 8 |
| 5 | 2 |
EDIT:
Following some answers I got:
SELECT t1.id, t1.val + SUM(t2.val) AS val
FROM table1 t1
LEFT JOIN table2 t2 ON (t1.id = t2.id)
GROUP BY t1.id
what gives me:
id val
1 2
2 5
3 7
4 8
5 NULL
But 2 plus nothing = 2 and not NULL. Is there a different way?
You forgot to group by:
SELECT t1.id, t1.val - SUM(t2.val) AS val
FROM t1
JOIN table2 t2 ON (t1.id = t2.id)
GROUP BY t1.id
of course, I'm not sure why you're trying to subtract the values in your sample query. maybe you meant + instead?
use union instead of join:
select id, sum(val)
(
SELECT t1.id, t1.val as val
FROM table1 t1
union all # note this change to include all the value from 2 table
select t2.id, t2.val as val
from table2 t2
) as unionTable
groupby id;
Related
I got 3 tables
| ID | Name |
|:---- |:------:|
| 1 | Brie |
| 2 | Ray |
| 3 | James |
Table2
| ID | Q_id | Q_no | ans |
|:---- |:------:| -----:|----:|
| 1 | 2304. | 1 | A |
| 1 | 2304. | 2 | A |
| 1 | 2305. | 1 | C |
| 2 | 2304. | 2 | A |
| 2 | 2305. | 1 | C |
| 3 | 2304. | 1 | A |
| 3 | 2305. | 2 | D |
Table3
| Q_id | Q_no | correct_ans |
|:------:| -----:|------------:|
| 2304. | 1 | A |
| 2304. | 2 | B |
| 2305. | 1 | C |
| 2305. | 2 | D |
I need to print a table with ID, name and count of ans in table 2 where ans matches with correct answer from table 3
| ID | Name | ans_count |
|:---- |:------:| ----------:|
| 1 | Brie | 2 |
| 2 | Ray | 1 |
| 3 | James | 2 |
Select t1.ID, Name, count(t2.ans) as ans_count
from Table1 t1
join Table2 t2 on t1.ID=t2.ID
join Table3 t3 on t2.Q_id=t3.Q_id
where t2.ans=t3.correct.ans and t2.q_no=t3.q_no
group by t1.ID
order by t1.ID
Where am I doing it wrong? Sorry I am new to SQL.
You should always link the tables, with all colums that match
AND the GROUP By should contain all columns that have no aggregation function
SELECT t1.ID,t1.`Name`,COUNT(*) as correct_answers
FROM table1 t1
JOIN table2 t2 ON t1.ID = t2.ID
JOIN table3 t3 ON t2.`Q_id` = t3.`Q_id` AND t2.`Q_no` = t3.`Q_no`
WHERE t3.`correct_ans` = t2.`ans`
GROUP BY t1.ID,t1.`Name`
order by t1.ID
ID
Name
correct_answers
1
Brie
2
2
Ray
1
3
James
2
fiddle
Its still not clear what you are after, but this corrects the obvious issue with the query.
Select t1.ID, Name, count(*) as ans_count
from Table1 t1
join Table2 t2 on t1.ID=t2.ID
join Table3 t3 on t2.Q_id=t3.Q_id
where t2.ans=t3.correct.ans
group by t1.ID, t1.Name ///<---------------
order by t1.ID
I think you need to group by Id and Name
I need a solution for a rather complex mySQL join:
Say we have 3 tables: T1, T2 and T3.
Table 1 contains the main ID and a name field.
Table1
| ID | Name |
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
Table 2 contains a column for the Table 1's ID and a value
Table2
| ID | oID | Value |
| 1 | 1 | aaa |
| 2 | 1 | bbb |
| 3 | 1 | ccc |
| 4 | 2 | ddd |
| 5 | 2 | eee |
| 6 | 3 | fff |
| 7 | 3 | ggg |
| 8 | 3 | hhh |
| 9 | 4 | iii |
So far so good, a simple JOIN will get me the Table2.Values linked to the Table1.Name
But there is also Table 3
Table3
| ID | oID | Condition | Value |
| 1 | 1 | color | red |
| 2 | 1 | brightness | 20 |
| 3 | 2 | color | green |
| 4 | 2 | brightness | 50 |
| 5 | 2 | saturation | 100 |
| 6 | 3 | color | green |
| 7 | 3 | brightness | 40 |
| 8 | 3 | saturation | 70 |
| 9 | 4 | color | purple|
What I need to do is get the T1.Name, with all the related T2.Values ONLY IF 2 (or more) conditions of T3 are OK:
For example:
All Names with matching T2.Values IF T3.Condition = 'green' AND T3.brightness = 50
As only ID 2 is green with a brightness of 50, that should give me
B ddd
B eee
I have tried several things:
SELECT t1.ID,
t1.Name,
t2.Value
FROM
Table1 t1
JOIN Table2 t2 ON t1.ID = t2.oID
JOIN Table3 t3 ON t1.ID = t3.oID
WHERE
t3.Condition = 'color'
AND
t3.Value = 'green'
AND
t3.Condition = 'brightness'
AND
t3.Value = 50
GROUP BY p.ID
Resulting in nothing of course, as no record has all four conditions
SELECT t1.ID,
t1.Name,
t2.Value
FROM
Table1 t1
JOIN Table2 t2 ON t1.ID = t2.oID
JOIN Table3 t3 ON t1.ID = t3.oID
WHERE
(t3.Condition = 'color' AND t3.Value = 'green')
AND
(t3.Condition = 'brightness'AND t3.Value = 50)
GROUP BY p.ID
Same result: nothing
SELECT t1.ID,
t1.Name,
t2.Value
FROM
Table1 t1
JOIN Table2 t2 ON t1.ID = t2.oID
JOIN Table3 t3 ON t1.ID = t3.oID
WHERE
(t3.Condition = 'color' AND t3.Value = 'green')
OR
(t3.Condition = 'brightness' AND t3.Value = 50)
GROUP BY p.ID
I get all records with brightness 50 and those with color green... but not those with both those conditions.
I also tried with conditions in the JOIN ON statement, LEFT JOINS, WHERE condition IN (..,..) and so on but without success.
The one who finds the solution gets eternal fame!
SELECT * FROM table3;
+----+-----+------------+--------+
| ID | oID | condition | value |
+----+-----+------------+--------+
| 1 | 1 | color | red |
| 2 | 1 | brightness | 20 |
| 3 | 2 | color | green |
| 4 | 2 | brightness | 50 |
| 5 | 2 | saturation | 100 |
| 6 | 3 | color | green |
| 7 | 3 | brightness | 40 |
| 8 | 3 | saturation | 70 |
| 9 | 4 | color | purple |
+----+-----+------------+--------+
9 rows in set (0.00 sec)
mysql>
SELECT x.oid
FROM table3 x
WHERE (x.condition,x.value) IN(('color','green'),('brightness','50'))
GROUP
BY x.oid
HAVING COUNT(*) = 2;
+-----+
| oid |
+-----+
| 2 |
+-----+
Note that condition is a reserved word, making it a less than ideal choice as a table/column identifier
What you are doing wrong is that you join table3 to the other 2 tables.
Instead you should join a subquery of table3 which returns the oIDs that meet your conditions:
SELECT t1.name, t2.value
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.oid
INNER JOIN (
SELECT oID FROM table3
GROUP BY oID
HAVING SUM(`condition` = 'color' AND value = 'green') > 0
AND SUM(`condition` = 'brightness' AND value = '50') > 0
) t3 ON t1.id = t3.oID
See the demo.
Results:
| name | value |
| ---- | ----- |
| B | ddd |
| B | eee |
On table1
+-------+-------+
| unid1 | unid2 |
+-------+-------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+-------+-------+
On table 2
+---------+-------+-------+------+
| tableid | unid1 | unid2 | type |
+---------+-------+-------+------+
| 1 | 1 | 1 | 1 |
| 2 | 2 | 2 | 1 |
| 3 | 3 | 3 | 1 |
| 4 | 3 | 0 | 2 |
| 5 | 3 | 0 | 2 |
| 6 | 4 | 4 | 3 |
| 7 | 5 | 5 | 3 |
+---------+-------+-------+------+
Expected result.
+-------+-------+------+
| unid1 | unid2 | type |
+-------+-------+------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
| 3 | 0 | 2 |
| 3 | 0 | 2 |
+-------+-------+------+
My SQL code
select t1.*, t2.* from table1 t1
left join table2 t2 on t1.unid1 = t2.unid1 and t1.unid2 = t2.unid2 and
t2.type in (1 , 2);
My SQL query does not give the result that i wanted, how can i get the result that i want.
Your expected output implies that you want to retain all rows in table2 whose unid1 values can be found in table1. If so, then we can just inner join these two tables on the unid1 column. This assumes that unid1 is unique in table1.
SELECT t2.unid1, t2.unid2, t2.type
FROM table2 t2
INNER JOIN table1 t1
ON t2.unid1 = t1.unid1;
If I understand you correctly, you want to output values wherein the rows from Table1 matches on Table2 in both columns unid1 and unid2 and that the type must be contained with your desired values.
SELECT b.unid1, b.unid2, b.type
FROM table1 a
INNER JOIN table2 b
ON a.unid1 = b.unid1
WHERE EXISTS
(
SELECT 1
FROM Table1 t1
INNER JOIN Table2 t2
ON t1.unid1 = t2.unid1
AND t1.unid2 = t2.unid2
WHERE t2.type in (1,2)
AND a.unid1 = t1.unid1
)
Here's a DEMO.
I have a table like this:
// tags
+----+--------------+-----------+---------+
| id | tag_name | parent_id | related |
+----+--------------+-----------+---------+
| 1 | programming | NULL | 1 |
| 2 | medical | NULL | 2 |
| 3 | juridical | NULL | 3 |
| 4 | HTML | 1 | 1 |
| 5 | PHP | 1 | 1 |
| 6 | function | 5 | 1 |
| 7 | ampoule | 2 | 2 |
| 8 | needle | 7 | 2 |
| 9 | CSS | 1 | 1 |
| 10 | echo | 5 | 1 |
| 11 | padding | 9 | 1 |
+----+--------------+-----------+---------+
Also I have this value: function. Now I want to select all its parents. So this is expected result:
+----+--------------+-----------+---------+
| id | tag_name | parent_id | related |
+----+--------------+-----------+---------+
| 1 | programming | NULL | 1 |
| 5 | PHP | 1 | 1 |
+----+--------------+-----------+---------+
How can I do that?
Note: related column has nothing to do with this question. It've added it because sometimes I need to select all related tags (both parents and children).
It might be better to get one level at a time from your code to get his data. But if you know how many levels you have in your hierarchies you can prepare code for this.
If you have a maximum of 4 hierarchies including the last level this code would work. Then you can add more unions for more levels or remove the last union if you dont have as many levels.
I have set the name 'tableName' on your table here and just wrote it together quickly but this should work. Let me know if it does not work and i will try to find a mysql server to run against.
SELECT t1.*
FROM tableName t1
JOIN tableName t2 ON t1.id = t2.parent_id
WHERE t2.tag_name = 'function'
UNION ALL
SELECT t1.*
FROM tableName t1
JOIN tableName t2 ON t1.id = t2.parent_id
JOIN tableName t3 ON t2.id = t3.parent_id
WHERE t3.tag_name = 'function'
UNION ALL
SELECT t1.*
FROM tableName t1
JOIN tableName t2 ON t1.id = t2.parent_id
JOIN tableName t3 ON t2.id = t3.parent_id
JOIN tableName t4 ON t3.id = t4.parent_id
WHERE t4.tag_name = 'function'
ORDER BY ID
(Changing 'function' to a variable is of course a good idea)
I have the following tables:
table1: table2: table3:
| id | | id | | id |
|------| |------| |------|
| 1 | | 1 | | 1 |
| 2 | | 2 | | 2 |
How can I execute a MySql Query which inserts into a 4th table (table4) all possible combinations of the above tables which has according columns (id1, id2, id3)?
Basically I want my table4 to look like this:
| id1 | id2 | id3 |
|-----|-----|-----|
| 1 | 1 | 1 |
| 1 | 1 | 2 |
| 1 | 2 | 1 |
| 1 | 2 | 2 |
| 2 | 1 | 1 |
| 2 | 1 | 2 |
| 2 | 2 | 1 |
| 2 | 2 | 2 |
You would use create table as and cross join:
create table table4 as
select t1.id as id1, t2.id as id2, t3.id as id3
from table1 t1 cross join
table2 t2 cross join
table3 t3;
Note that SQL tables represent unordered sets. So, if you want to see the results in the order you have specified, then use:
select t4.*
from table4 t4
order by id1, id2, id3;