SQL Union and Merge Subset Tables - mysql

T1
SCHOOL STUDENT TEACHER
1 1 A
1 2 B
1 3 B
1 4 B
T2
SCHOOL STUDENT TEACHER
2 7 A
2 6 A
2 8 B
2 9 B
T3
SCHOOL TEACHER ID
1 A FOX
1 B CAT
2 A DOG
2 B MOUSE
T4
SCHOOL STUDENT TEACHER ID
1 1 A FOX
1 2 B CAT
1 3 B CAT
1 4 B CAT
2 7 A DOG
2 6 A DOG
2 8 B MOUSE
2 9 B MOUSE
I have T1 T2 T3 where I wish to UNION T1 and T2 and afterwards JOIN T3 such as:
SELECT * FROM T1
UNION
(SELECT * FROM T2)
JOIN
(SELECT SCHOOL, TEACHER, ID
WHERE SCHOOL != 10
FROM T3)
BUT I receive error "UNEXPECTED JOIN"

JOIN is a part of a SELECT statement while UNION are not.
So, you need to make UNION as a part of a SELECT statement
select * from (
SELECT * FROM T1
UNION
SELECT * FROM T2) q1
JOIN
(SELECT SCHOOL, TEACHER, ID
FROM T3
WHERE SCHOOL != 10) q2
on /* here goes JOIN condition you need, like q1.school = q2.school*/
Please note:
there is another syntax error in your example: FROM goes always after SELECT and before WHERE
UNION will append result and eliminate duplicate rows which can run slower than UNION ALL. The latter will not check whether there are duplicate rows. So, if you're sure there won't be any duplicates in the result or if it's irrelevant whether you get duplicates or not, you may use UNION ALL

Related

SQL - Count two columns together

I'm trying to count multiple columns as one column. For example:
Table 1 (Books):
ID
BookName
Genre
SubGenre
1
Name1
1
3
2
Name2
2
1
3
Name3
4
2
Table 2 (Genre):
ID
Genre
1
Horror
2
Drama
3
Romance
4
Sci-Fi
I want to be able to count the genre and subgenre as one to create a table of:
Result:
Genre
Count
Horror
2
Drama
2
Romance
1
Sci-Fi
1
Any help would be really appreciated. Thanks
Try below query-
SELECT t.Genre, Sum(t.cg) AS Count
FROM (
SELECT t2.Genre, Count(t1.Genre) AS cg
FROM Table2 as t2 LEFT JOIN Table1 as t1 ON t2.ID = t1.Genre
GROUP BY t2.Genre
UNION ALL
SELECT t2.Genre, Count(t1.SubGenre) AS cg
FROM Table2 as t2 LEFT JOIN Table1 as t1 ON t2.ID = t1.SubGenre
GROUP BY t2.Genre
) as t GROUP BY t.Genre;

MySQL Select first entry of GROUP after custom ORDER BY

I'm trying to fetch the first entry of each group after the custom ORDER BY but don't know how to select that first entry of each group. The groups should be ordered by the #team if exist, otherwise other team else NULL.
SELECT t1.*
FROM tbl t1
INNER JOIN tbl2 t2 ON t2.group_id = t1.group
WHERE t2.region = #region
ORDER BY
CASE
WHEN team=#team THEN 1
WHEN team is NOT NULL THEN 2
WHEN team is NULL THEN 3
END
Content of tbl
id group team
1 1 AA
2 1 BB
3 2 AA
4 2 CC
5 3 BB
6 3 NULL
7 4 NULL
Expected result when #team=AA
id group team
1 1 AA
3 2 AA
5 3 BB
7 4 NULL
Expected result when #team=BB
id group team
2 1 BB
3 2 AA
5 3 BB
7 4 NULL
Use your custom ordering logic with ROW_NUMBER:
WITH cte AS (
SELECT t1.*, ROW_NUMBER() OVER (PARTITION BY t1.`group`
ORDER BY CASE WHEN team = #team THEN 1
WHEN team IS NOT NULL THEN 2
ELSE 3 END) rn
FROM tbl t1
INNER JOIN tbl2 t2 ON t2.group_id = t1.`group`
WHERE t2.region = #region
)
SELECT id, `group`, team
FROM cte
WHERE rn = 1;
Side note: Avoid naming your table columns GROUP, as this is a reserved MySQL keyword, and therefore must always be escaped in backticks.

Identify missing conversions with an SQL query

I need to find a way to find what conversions are missing.
I have three tables.
Table 1: type, which are the different types.
id
name
1
typeA
2
typeB
3
typeC
Table 2: section, which are the different sections.
id
name
1
section1
2
section2
3
section3
4
section4
Table 3: conversions, which contains all the combinations to go from one type to another for each of the sections.
id
section_id
type_convert_from
type_convert_to
1
1
1
2
2
2
1
2
3
3
1
2
4
4
1
2
5
1
1
3
6
2
1
3
7
3
1
3
8
4
1
3
9
1
2
1
10
2
2
1
11
3
2
1
12
4
2
1
For example some are missing from the table above, how can I identify them with a SQL query? Thanks!
Try this. The cross join of table type with itself generates all possible combinations of type id's. I've excluded combinations in the cross join where id_from = id_to (ie you're not interested in conversions from a type to itself)
select * from conversions C
right join (
select T1.id as id_from, T2.id as id_to
from type T1 cross join type T2
where T1.id <> T2.id
) X on X.id_from = C.type_convert_from and X.id_to = C.type_convert_to
where C.type_convert_from is null
If you want to check missing type conversions by section, extend the cross join by adding the section table to include section.id as follows. It will list missing type conversions within each section.
select X.section_id, X.id_from, X.id_to from conversions C
right join (
select S.id as section_id, T1.id as id_from, T2.id as id_to
from types T1 cross join types T2 cross join section S
where T1.id <> T2.id
) X
on X.id_from = C.type_convert_from and X.id_to = C.type_convert_to
and C.section_id = X.section_id
where C.type_convert_from is null

How to do Nested Queries in SQL

I'm trying to learn SQL, and while I'm slowly learning how to query data, I'm stuck on querying the results of a query. Take this example
I want an SQL statement to do 2 things. Suppose I have 2 tables like the one below (table 1 borrowed from another example on stack overflow)
Table 1:
ID game point time
1 x 5 7:00
1 z 4 11:00
2 y 6 9:00
3 x 2 2:00
3 y 5 4:00
3 z 8 6:00
4 k 0 8:00
Table 2:
id tv chan
1 cab
2 trop
3 start
4 cab
The first thing I want to do is combine certain columns from these tables. I know I can select these columns and do an inner join on ID
However the second thing I want to do is drop all the rows with point value 0, and then have only rows with distinct game name with the lowest point value. So I want the final table to look like this
id game point tv chan
1 z 4 cab
2 y 5 trop
3 x 2 start
Thanks
You could try something like this:
SELECT t1.ID,
t1.game,
t1.point,
t2.tv_chan
FROM Table1 AS t1
INNER JOIN Table2 AS t2 ON t2.id = t1.id
INNER JOIN (SELECT t11.game, MIN(t11.point) AS min_point
FROM Table1 AS t11
WHERE t11.point != 0
GROUP BY t11.game
) AS t3 ON t3.game = t1.game
AND t3.min_point = t1.point
WHERE t1.point != 0
You could use a join with a subquery that group by id and game for obtain the min point
select t1.id, t1.game. t1.point, t2 `tv chan`
from (
select id, game, min(point) point
from table1
where point > 0
group by id, game
) t1
inner join table2 t2 on t1.id = t2.id

MySQL distinct values query

I need help with a relatively simple query. For a table:
A | B | C
----------
2 1 6
2 2 5
3 3 4
4 4 3
5 5 2
6 6 1
I need to have an output like so:
A | B | C
----------
2 1 6
3 3 4
4 4 3
5 5 2
6 6 1
So that each value in A is distinct, but I also get the corresponding values in B and C. I know "select distinct(A) from table" but that only returns the values 2,3,4,5,6 and I need the values in columns B and C, too. Please help. I have a deadline fast approaching. This question is stupid and trivial, but one must walk before they can run. Thanks so much.
Try this:
SELECT T1.A, T1.B, MIN(T1.C) AS C
FROM yourtable T1
JOIN (
SELECT A, MIN(B) AS B
FROM yourtable
GROUP BY A
) T2
ON T1.A = T2.A AND T1.B = T2.B
GROUP BY T1.A, T1.B
SELECT DISTINCT(A), B, C
FROM table
Is there a specific logic behind which distinct A rows you want to select when considering columns B and C?