我不确定我想要使用联合做什么,或者我是否需要使用嵌套查询和某种联接。
select c1,c2 from t1
union
select c1,c2 from t2
// with some sort of condition where t1.c1 = t2.c1
示例:
t1
| 100 | regular |
| 200 | regular |
| 300 | regular |
| 400 | regular |
t2
| 100 | summer |
| 200 | summer |
| 500 | summer |
| 600 | summer |
Desired Result
| 100 | regular |
| 100 | summer |
| 200 | regular |
| 200 | summer |
我尝试过类似的事情:
select * from (select * from t1) as q1
inner join
(select * from t2) as q2 on q1.c1 = q2.c1
但是这会将记录加入到这样的单行中:
| 100 | regular | 100 | summer |
| 200 | regular | 200 | summer |
答案 0 :(得分:1)
尝试:
select c1, c2
from t1
where c1 in (select c1 from t2)
union all
select c1, c2
from t2
where c1 in (select c1 from t1)
根据编辑,请尝试以下操作:
MySQL没有WITH子句允许你多次引用你的t1和t2 subs。您可能希望在数据库中创建t1和t2作为视图,以便在单个查询中多次将它们称为t1和t2。
即便如此,下面的查询老实地看起来非常糟糕,如果我们知道您的数据库结构,可能会进行很多优化。 IE浏览器。表的列表,每个表上的所有列及其数据类型,每个表的几个示例行以及您的预期结果。
例如在你的t1子中你有一个带有LESSON表的外连接,但是你的WHERE子句中有标准(lesson.dayofweek> = 0),这自然不允许空值,有效地转动你的外表加入内部联接。此外,您还有子查询仅使用标准来检查studentid是否存在,这些标准表明实际上不需要使用多个表来生成所需的结果。但是,如果不知道您的数据库结构和一些具有预期结果的示例数据,则很难进一步建议。
即使如此,我相信下面的内容可能会让你得到你想要的东西,而不是最佳。
select *
from (select distinct students.student_number as "StudentID",
concat(students.first_name, ' ', students.last_name) as "Student",
general_program_types.general_program_name as "Program Category",
program_inventory.program_code as "Program Code",
std_lesson.studio_name as "Studio",
concat(teachers.first_name, ' ', teachers.last_name) as "Teacher",
from lesson_student
left join lesson
on lesson_student.lesson_id = lesson.lesson_id
left join lesson_summer
on lesson_student.lesson_id = lesson_summer.lesson_id
inner join students
on lesson_student.student_number = students.student_number
inner join studio as std_primary
on students.primary_location_id = std_primary.studio_id
inner join studio as std_lesson
on (lesson.studio_id = std_lesson.studio_id or
lesson_summer.studio_id = std_lesson.studio_id)
inner join teachers
on (lesson.teacher_id = teachers.teacher_id or
lesson_summer.teacher_id = teachers.teacher_id)
inner join lesson_program
on lesson_student.lesson_id = lesson_program.lesson_id
inner join program_inventory
on lesson_program.program_code_id =
program_inventory.program_code_id
inner join general_program_types
on program_inventory.general_program_id =
general_program_types.general_program_id
inner join accounts
on students.ACCOUNT_NUMBER = accounts.ACCOUNT_NUMBER
inner join account_contacts
on students.ACCOUNT_NUMBER = account_contacts.ACCOUNT_NUMBER
/** NOTE: the WHERE condition is the only **/
/** difference between subquery1 & subquery2 **/
where lesson.dayofweek >= 0 and
order by students.STUDENT_NUMBER) t1
where StudentID in
(select StudentID
from (select distinct students.student_number as "StudentID",
concat(students.first_name,
' ',
students.last_name) as "Student",
general_program_types.general_program_name as "Program Category",
program_inventory.program_code as "Program Code",
std_lesson.studio_name as "Studio",
concat(teachers.first_name,
' ',
teachers.last_name) as "Teacher",
from lesson_student
left join lesson
on lesson_student.lesson_id = lesson.lesson_id
left join lesson_summer
on lesson_student.lesson_id = lesson_summer.lesson_id
inner join students
on lesson_student.student_number =
students.student_number
inner join studio as std_primary
on students.primary_location_id = std_primary.studio_id
inner join studio as std_lesson
on (lesson.studio_id = std_lesson.studio_id or
lesson_summer.studio_id = std_lesson.studio_id)
inner join teachers
on (lesson.teacher_id = teachers.teacher_id or
lesson_summer.teacher_id = teachers.teacher_id)
inner join lesson_program
on lesson_student.lesson_id = lesson_program.lesson_id
inner join program_inventory
on lesson_program.program_code_id =
program_inventory.program_code_id
inner join general_program_types
on program_inventory.general_program_id =
general_program_types.general_program_id
inner join accounts
on students.ACCOUNT_NUMBER = accounts.ACCOUNT_NUMBER
inner join account_contacts
on students.ACCOUNT_NUMBER =
account_contacts.ACCOUNT_NUMBER
/** NOTE: the WHERE condition is the only **/
/** difference between subquery1 & subquery2 **/
where lesson_summer.dayofweek >= 0
order by students.STUDENT_NUMBER) t2)
UNION ALL
select *
from (select distinct students.student_number as "StudentID",
concat(students.first_name, ' ', students.last_name) as "Student",
general_program_types.general_program_name as "Program Category",
program_inventory.program_code as "Program Code",
std_lesson.studio_name as "Studio",
concat(teachers.first_name, ' ', teachers.last_name) as "Teacher",
from lesson_student
left join lesson
on lesson_student.lesson_id = lesson.lesson_id
left join lesson_summer
on lesson_student.lesson_id = lesson_summer.lesson_id
inner join students
on lesson_student.student_number = students.student_number
inner join studio as std_primary
on students.primary_location_id = std_primary.studio_id
inner join studio as std_lesson
on (lesson.studio_id = std_lesson.studio_id or
lesson_summer.studio_id = std_lesson.studio_id)
inner join teachers
on (lesson.teacher_id = teachers.teacher_id or
lesson_summer.teacher_id = teachers.teacher_id)
inner join lesson_program
on lesson_student.lesson_id = lesson_program.lesson_id
inner join program_inventory
on lesson_program.program_code_id =
program_inventory.program_code_id
inner join general_program_types
on program_inventory.general_program_id =
general_program_types.general_program_id
inner join accounts
on students.ACCOUNT_NUMBER = accounts.ACCOUNT_NUMBER
inner join account_contacts
on students.ACCOUNT_NUMBER = account_contacts.ACCOUNT_NUMBER
/** NOTE: the WHERE condition is the only **/
/** difference between subquery1 & subquery2 **/
where lesson_summer.dayofweek >= 0
order by students.STUDENT_NUMBER) x
where StudentID in
(select StudentID
from (select distinct students.student_number as "StudentID",
concat(students.first_name,
' ',
students.last_name) as "Student",
general_program_types.general_program_name as "Program Category",
program_inventory.program_code as "Program Code",
std_lesson.studio_name as "Studio",
concat(teachers.first_name,
' ',
teachers.last_name) as "Teacher",
from lesson_student
left join lesson
on lesson_student.lesson_id = lesson.lesson_id
left join lesson_summer
on lesson_student.lesson_id = lesson_summer.lesson_id
inner join students
on lesson_student.student_number =
students.student_number
inner join studio as std_primary
on students.primary_location_id = std_primary.studio_id
inner join studio as std_lesson
on (lesson.studio_id = std_lesson.studio_id or
lesson_summer.studio_id = std_lesson.studio_id)
inner join teachers
on (lesson.teacher_id = teachers.teacher_id or
lesson_summer.teacher_id = teachers.teacher_id)
inner join lesson_program
on lesson_student.lesson_id = lesson_program.lesson_id
inner join program_inventory
on lesson_program.program_code_id =
program_inventory.program_code_id
inner join general_program_types
on program_inventory.general_program_id =
general_program_types.general_program_id
inner join accounts
on students.ACCOUNT_NUMBER = accounts.ACCOUNT_NUMBER
inner join account_contacts
on students.ACCOUNT_NUMBER =
account_contacts.ACCOUNT_NUMBER
/** NOTE: the WHERE condition is the only **/
/** difference between subquery1 & subquery2 **/
where lesson.dayofweek >= 0 and
order by students.STUDENT_NUMBER) x);
答案 1 :(得分:0)
为了比较两个表中的值,您需要进行连接。我看到的第一种方法是使用内部联接进行2次查询并将它们联合起来:
select t1.* from t1
inner join t2 using (c1)
union
select t2.* from t1
inner join t2 using (c1)
但是,我们可以做得更好:您可以看到我使用完全相同的查询,直到我在结果集中选择哪些列,这有点浪费。如果我们可以简单地复制每个记录(1)?好吧,我们可以:
select * from t1
inner join t2 using (c1)
cross join (
select 0 as parity
union
select 1 as parity) dup
现在我们将所有内容都设置为double,并且有一个额外的奇偶校验列,我们只需要在其上选择一组列:
-- broken query
select case parity when
0 then t1.*
1 then t2.*
end from t1
inner join t2 using (c1)
cross join (
select 0 as parity
union
select 1 as parity) dup
不幸的是,case
表达式不允许返回多个列,因此我们需要为所有列包含测试。在您的情况下,一列足够了:
select c1, case parity when
0 then t1.c2
1 then t2.c2
end from t1
inner join t2 using (c1)
cross join (
select 0 as parity
union
select 1 as parity) dup
order by c1
-- order by parity, c1
使用已注释的order by
来获取t1
的结果集,然后是t2
。
警告:代码未经测试。
(1)这个在ANSI SQL中称为CTE的功能(99我认为)允许分解出一个公共查询,然后在整个主查询中引用它,但遗憾的是mysql不支持它。
答案 2 :(得分:0)
UNION
没问题。
您希望运行相同的加入两次。除了第一次超过你,左边第二次。
SELECT t1.* FROM t1 JOIN t2 USING (c1)
UNION
SELECT t2.* FROM t1 JOIN t2 USING (c1)
当然,如果可能的话,您可以运行单个查询并将左侧保存在内存中,显示右侧,然后将保存的左侧排队。它需要比游标更多的内存,但是在一半的时间内运行查询(实际上更少,因为磁盘和资源缓存)。
请参阅here示例SQLFiddle。