在MySQL中为UNION添加条件

时间:2014-07-04 18:49:26

标签: mysql sql

我不确定我想要使用联合做什么,或者我是否需要使用嵌套查询和某种联接。

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 |

3 个答案:

答案 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。