Say I have a query which looks something like this:
select step0.a, step1.a, step2.a
from (select id from tbl1) as step
inner join tbl1 as step0 on step0.id = step.id
left join tbl1 as step1 on step1.b = step0.a
left join tbl1 as step2 on step2.b = step1.a
This works fine. Now, say I want to union these results with the reverse of a and b, i.e.:
select * from (
(
select step0.a, step1.a, step2.a
from (select id from tbl1) as step
inner join tbl1 as step0 on step0.id = step.id
left join tbl1 as step1 on step1.b = step0.a
left join tbl1 as step2 on step2.b = step1.a
)
union (
select step0.b, step1.b, step2.b
from (select id from tbl1) as step
inner join tbl1 as step0 on step0.id = step.id
left join tbl1 as step1 on step1.a = step0.b
left join tbl1 as step2 on step2.a = step1.b
)
) rows
This also works fine. But notice that the select id from tbl1 subquery is duplicated.
The question I have, is how do I store the results of this subquery, without using temporary tables, such that each select in the union can reference it?
Related
I am trying to join two tables and get the count and grouped by specific field. However, it outputs same count values even if the other table consist only two rows. How should I fix this?
Here's my code:
SELECT tbl1.preferredDay, COUNT(tbl1.preferredDay) as count_1, COUNT(tbl2.preferredDay) as count_2
FROM tblschedule as tbl1
LEFT JOIN tblappointments as tbl2 ON (tbl1.preferredDay = tbl2.preferredDay)
WHERE tbl1.preferredDay = tbl2.preferredDay
GROUP BY preferredDay;
Here is the output but it should be [15, 0][3, 3]
Your query is based on left join it will return the same count().
This is a working query for Mysql 8:
with tbl1 as (
SELECT preferredDay, count(1) as count_1
FROM tblschedule
GROUP BY preferredDay
),
tbl2 as (
SELECT preferredDay, count(1) as count_2
FROM tblappointments
GROUP BY preferredDay
)
select t1.preferredDay, t1.count_1, t2.count_2
from tbl1 t1
inner join tbl2 t2 on t1.preferredDay = t2.preferredDay
There are two WITHs to get separately the count and then an INNER JOIN to join those results
For Mysql 5.7 and lower :
select t1.preferredDay, t1.count_1, t2.count_2
from (
SELECT preferredDay, count(1) as count_1
FROM tblschedule
GROUP BY preferredDay
) as t1
inner join (
SELECT preferredDay, count(1) as count_2
FROM tblappointments
GROUP BY preferredDay
) as t2 on t1.preferredDay = t2.preferredDay
I'm doing UNION in MySQL that I'm unable to troubleshoot for a while.
Error says that
syntax is incorrect around t1.*
Those 2 SELECTs work ok separately, checked. But UNION fails. I'm not custom to MySQL syntax, maybe something is wrong with that.
SELECT (
t1.*,
a.region_count
FROM
(
SELECT
data_region,
COUNT(*) AS region_count
FROM
t2
GROUP BY
data_region
) AS a
LEFT OUTER JOIN
t1
ON
t1.values_att0 = a.data_region
WHERE
t1.name_0 = 'region'
) AS b
UNION
SELECT (
t1.*,
c.age_gen_count
FROM
(
SELECT
data_dage,
data_gen,
COUNT(*) AS age_gen_count
FROM
t2
GROUP BY
data_dage,
data_gen
) AS c
LEFT JOIN
t1
ON
t1.values_att0 = c.data_dage AND
t1.id_question_1 = c.data_gen
WHERE
t1.name_0 = 'age' AND
t1.q_name_1 = 'gen'
)
You are using parenthesis around your SELECT field, this is your syntax error origin (the UNION is not the cause). Just remove them:
SELECT
t1.*,
a.region_count
FROM
(
SELECT
data_region,
COUNT(*) AS region_count
FROM t2
GROUP BY data_region
) AS a
LEFT OUTER JOIN t1
ON t1.values_att0 = a.data_region
WHERE t1.name_0 = 'region'
UNION ALL
SELECT
t1.*,
c.age_gen_count
FROM
(
SELECT
data_dage,
data_gen,
COUNT(*) AS age_gen_count
FROM t2
GROUP BY data_dage, data_gen
) AS c
LEFT JOIN t1
ON t1.values_att0 = c.data_dage
AND t1.id_question_1 = c.data_gen
WHERE t1.name_0 = 'age'
AND t1.q_name_1 = 'gen'
I have 2 identical dead-simple tables in a MySQL database with different data. I need a single query that will return all the results that aren't a duplicate.
Here's an example:
Table 1. (column "item")
a
b
c
d
Table 2. (column "item")
a
b
e
f
x
Wanted Result
c
d
e
f
x
Try this -
SELECT * FROM TABLE1 WHERE ITEM NOT IN (SELECT ITEM FROM TABLE2)
UNION
SELECT * FROM TABLE2 WHERE ITEM NOT IN (SELECT ITEM FROM TABLE1)
You can use NOT EXISTS, e.g.:
SELECT item
FROM table1 t1
WHERE NOT EXISTS (
SELECT item FROM table2 WHERE item = t1.item
);
We could join them using a distinct an union ALL. then count and having.
the distinct is needed since we care about unique accross the sets.
SELECT item FROM (
SELECT distinct item
FROM tbl1
UNION ALL
SELECT distinct item
FROM tbl2) B
GROUP BY item
HAVING count(*) =1
SELECT * FROM TABLE1 WHERE ITEM NOT IN (SELECT ITEM FROM TABLE2)
union
SELECT * FROM TABLE2 WHERE ITEM NOT IN (SELECT ITEM FROM TABLE1)
Or another method would be to use an inner join to grab all the duplicate data and then pull all the data that isn't in your duplicate dataset.
SELECT * into #temptable FROM TABLE1 INNER JOIN TABLE2 on table2.x = table1.x
union
SELECT * into #temptable FROM TABLE2 INNER JOIN TABLE1 on table2.x = table1.x
SELECT * FROM Table1 WHERE NOT IN (SELECT * FROM #temptable)
UNION
SELECT * FROM Table2 WHERE NOT IN (SELECT * FROM #temptable)
A lot like xQbert's, but with the assumption that item is UNIQUE/PRIMARY...
SELECT a.*
FROM
( SELECT item FROM table1
UNION ALL
SELECT item FROM table2
) a
GROUP
BY item
HAVING COUNT(*) = 1;
I have a query like this.
SELECT count(*)
FROM table1 e
WHERE e.column1=1
AND e.id IN
(SELECT MAX(ID)
FROM table2 A
WHERE A.column1=1
AND A.date=CURDATE()
GROUP BY A.column2);
When I run this query it is taking too much of time as I am having thousands of records. How can I tune the query to perform better.
Thanks in advance.
EDIT: column2 in table2 is id of Table1
Change in (. . .) To use join instead. Like
SELECT count(*)
FROM table1 AS e
Inner join
(
SELECT MAX(ID)
FROM table2 A
WHERE A.column1 = 1
AND A.date = CURDATE()
GROUP BY A.column2
) t2 on e.id = t2.id
WHERE e.column1 = 1
Maybe:
SELECT count(*)
FROM table1 e
WHERE e.column1=1
AND EXISTS
(SELECT *
FROM table2 A
WHERE A.column1=1
AND A.date=CURDATE()
AND A.ID = e.id);
I am joining 2 tables -tbl1 and tbl2. Left join give all data from tbl1 which is in tbl2 or only on tbl1. Right join gives data from tbl2 which is don't exists in tbl1.
I want to combine both results.
What is the best way to do this so that I get all data from tbl1 and tbl2?
The only you can do that is by using UNION. MySQL doesn't support FULL JOINjust like in MSSQL.
SELECT *
FROM tbl1 t1
LEFT JOIN tbl2 t2
ON t1.col = t2.col
UNION
SELECT *
FROM tbl1 t1
RIGHT JOIN tbl2 t2
ON t1.col>= t2.<col
SEE HERE: Simulating FULL JOIN in MYSQL
By the way, UNION has optional keyword ALL,when the ALL is omitted, UNION automatically selects DISTINCT rows from the resultset.
EXAMLE:
SELECT *
FROM tableA
UNION ALL
SELECT *
FROM tableA
this can result duplicates rows
ColA ColB
==================
1 John
2 Jade
2 Jade
3 Hello
BUT if you omit the word ALL
SELECT *
FROM tableA
UNION
SELECT *
FROM tableA
this can result distinct rows only
ColA ColB
==================
1 John
2 Jade
3 Hello
What you want is FULL JOIN
LEFT JOIN + RIGHT JOIN = FULL JOIN
So try this:
SELECT * FROM tbl1
LEFT JOIN tbl2 ON tbl1.id = tbl2.id
UNION
SELECT * FROM tbl1
RIGHT JOIN tbl2 ON tbl1.id = tbl2.id
The UNION clause combines the results of two SQL queries into a single table of all matching rows.
Here's an alternative that can be easily extended if you have a full join of more than 2 tables:
SELECT t1*, t2.*
FROM
( SELECT col
FROM tbl1
UNION
SELECT col
FROM tbl2
) AS d
LEFT JOIN tbl1 AS t1
ON t1.col = d.col
LEFT JOIN tbl2 AS t2
ON t2.col = d.col ;
you have to use FULL OUTER JOIN, But mysql doesnt support it.. You could do this for getting the result:
SELECT *
FROM tbl1 t1 LEFT JOIN tbl2 t2
ON t1.<col> = t2.<col>
UNION
SELECT *
FROM tbl1 t1 RIGHT JOIN tbl2 t2
ON t1.<col>= t2.<col>