Select count of same entries in different tables - mysql

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

Related

MySQL JOIN Query Show Columns with IF ELSE Selected Option

I have 2 Tables named users & selected_users. I have show the structure of tables with some dummy values below.
Table: users AS t1
+----+--------+
| id | name |
+----+--------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
| 5 | E |
+----+--------+
Table: selected_users
+----+------------+
| id | users_id |
+----+------------+
| 1 | 2 |
| 2 | 5 |
+----+------------+
Desired Result:
+-------+----------+-----------+
| t1_id | t1_name | selected |
+-------+----------+-----------+
| 1 | A | NO |
| 2 | B | YES |
| 3 | C | NO |
| 4 | D | NO |
| 5 | E | YES |
+-------+----------+-----------+
What I have done:
I have written the following script.
SELECT t1.id AS t1_id, t1.name AS t1_name, CASE WHEN t2.t1_id=t1.id THEN 'YES' ELSE 'NO' END AS selected_in_t2
FROM t1
JOIN t2
But, Its showing me multiple values for each. Please help.
I did it using this Query.
SELECT t1.id AS t1_id, t1.name AS t1_name,
CASE WHEN t2.id IS NULL THEN 'No' ELSE 'Yes' END as selected
FROM t1
LEFT JOIN t2
ON t1.id = t2.t1_id ORDER BY t1.id

How to join tables on multiple records and multiple fields

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 |

get calculation from two tables related with a third table

i have this table
table1
| id | name |
| 1 | axe |
| 2 | bow |
| 3 | car |
| 4 | dart |
and these two tables
table2 table3
| t1_id | number | | t1_id | letter |
| 1 | 5 | | 1 | a |
| 1 | 6 | | 1 | b |
| 1 | 2 | | 1 | c |
| 2 | 2 | | 2 | a |
| 2 | 2 | | 2 | c |
| 2 | 3 | | 2 | r |
| 3 | 8 | | 3 | y |
| 3 | 3 | | 3 | i |
| 3 | 1 | | 3 | a |
| 4 | 8 | | 4 | a |
| 4 | 9 | | 4 | b |
| 4 | 10 | | 4 | c |
where in it t1_id is the table1 id
what i want to do is to get all table1 records having table3 letters a b c and the avg of their numbers like this order by the letter_count DESC first then by the avg_numbers DESC
| id | name | letter_count | avg_number |
| 4 | dart | 3 | 9 |
| 1 | axe | 3 | 4.3333333333 |
| 2 | bow | 2 | 2.3333333333 |
| 3 | car | 1 | 4 |
the query i expected to work properly was http://www.sqlfiddle.com/#!9/69086b/3/0
SELECT
t1.id,
t1.name,
COUNT(t3.letter) AS letter_count,
AVG(t2.number) AS avg_number
FROM
table1 t1
INNER JOIN
table2 t2
ON t2.t1_id = t1.id
LEFT JOIN
table3 t3
ON t3.t1_id = t1.id
AND t3.letter IN ('a', 'b', 'c')
GROUP BY
t1.id
ORDER BY
letter_count DESC,
avg_number DESC
but numbers are totally different and in accurate but the order is correct
i don't want to get the letter_count and avg_number values but i just want to order by them but their values are worrying me with the query performance
i wouldn't notice this weird values because my actual query is
SELECT
t1.id,
t1.name
FROM
table1 t1
INNER JOIN
table2 t2
ON t2.t1_id = t1.id
LEFT JOIN
table3 t3
ON t3.t1_id = t1.id
AND t3.letter IN ('a', 'b', 'c')
GROUP BY
t1.id
ORDER BY
COUNT(t3.letter) DESC,
AVG(t2.number) DESC
which only gives me proper ordery
| id | name |
| 4 | dart |
| 1 | axe |
| 2 | bow |
| 3 | car |
but after checking the values i was surprsied by the letter_count do i just ignore the values and it wouldn't affect the performance in my big table?
You are aggregating over two different dimensions. This causes a Cartesian product. One way to fix this is to aggregate before joining:
SELECT t1.id, t1.name, t2.letter_count, t2.avg_number
FROM table1 t1 INNER JOIN
(SELECT t2.t1_id, AVG(t2.number) as avg_number
FROM table2 t2
GROUP BY t2.t1_id
) t2
ON t2.t1_id = t1.id LEFT JOIN
(SELECT t3.t2_id, COUNT(t3.letter) as letter_count
FROM table3 t3
WHERE t3.letter IN ('a', 'b', 'c')
GROUP BY t3.t2_id
) t3
ON t3.t1_id = t1.id
ORDER BY t3.letter_count DESC, t2.avg_number DESC;
On the third table, IN-SELECT Subquery.
SELECT
t1.id,
t1.name,
(
SELECT count(letter)
FROM t3
where t3.t1_id = t1.id
) as lettercount,
AVG(t2.number) AS avg_number
FROM
table1 t1
INNER JOIN
table2 t2
ON t2.t1_id = t1.id

How can i join 2 tables with option values on certain column

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.

How to insert combinations from 3 tables into a 4th table with 3 corresponding columns?

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;