mysql complex加入

时间:2012-04-22 03:14:11

标签: mysql

我有一个由7个表组合的select语句

SELECT * (//instead of * i put in my code the proper columns i need from the selected tabls)
FROM 
ev_events_eve
LEFT JOIN ev_events_multilang_evmulti ON ev_events_multilang_evmulti.event_evmulti = ev_events_eve.id_eve
LEFT JOIN ev_schedule_sch ON ev_schedule_sch.event_id_sch = ev_events_eve.id_eve
LEFT JOIN ev_events_type_et ON ev_schedule_sch.event_type_id_sch = ev_events_type_et.id_et
LEFT JOIN ev_events_type_multilang_etmulti ON ev_events_type_multilang_etmulti.idevent_type_etmulti = ev_events_type_et.id_et
LEFT JOIN ev_schedule_multilang_schmulti ON ev_schedule_multilang_schmulti.id_schedule_schmulti = ev_schedule_sch.id_sch
LEFT JOIN ev_timetable_tt ON ev_timetable_tt.schedule_id_tt = ev_schedule_sch.id_sch AND ev_timetable_tt.event_id_tt = ev_events_eve.id_eve
WHERE (ev_events_eve.active_eve = 1 AND ev_schedule_multilang_schmulti.iso_code_lang_schmulti = '{$current_language}' AND ev_schedule_sch.active_sch = 1) AND
ev_timetable_tt.end_date_tt > CURDATE() OR (ev_timetable_tt.weekday_tt = DAYNAME(CURDATE()) AND ev_timetable_tt.end_date_tt > CURDATE()) OR ev_timetable_tt.specific_date_tt > CURDATE()
ORDER BY ev_timetable_tt.start_date_tt ASC LIMIT 3

这句话忽略了where子句的问题,每次我使用mysql我用来创建示例sql语句由两个或三个表组成,左边或内部正常连接,我需要有人和我讨论这个问题,它可以让我进一步看看我的代码中没有提到的东西,但是我知道上面的代码不足以让任何人跟我一起处理这个问题,但我需要有人可以跟我讨论

我使用以下信息更新了问题

主要业务规则:

  • 该项目适用于多语言网站

  • 表格是:
    • ev_events_eve(事件实体,如id,logo,标语,开头和结尾 整个活动的日期)
      • ev_events_multilang_evmulti(主要事件的多语言表 表格如名称(en,fr,gr ..等),描述......等)
      • ev_schedule_sch(调度实体,如id,事件表的外键)
      • ev_schedule_multilang_schmulti(主要的多语言表 时间表)
      • ev_timetable_tt(存储与之相关的开始和结束日期及时间 ev_schedule_sch表)

  • 每个表都被复制到两个表中,其中一个表用于存储 实体和另一个存储多语言数据的文件

  • 表之间的关系
    • 主表是ev_events_eve
    • ev_events_multilang_evmulti通过外国与主表相关 键
    • ev_schedule_sch related通过外键
    • 到主表
    • ev_schedule_multilang_schmultiev_schedule_sch表格相关 外键
    • ev_timetable_tt通过外键与ev_schedule_sch相关

我需要编写一个语句来从事件表中检索传入的3行(假设我需要检索最新的3行,因为你没有所有字段的完整模式,后来我们可以在WHERE子句:))加上这3行还从调度表中检索与事件表中每一行相关的6行 所以估计的结果必须是这样的 假设我有4个事件

  • 第一个被叫:事件#1
    • 此事件在计划相关表中有3行(因此检索
      所有这些行)


  • 第二个被叫:事件#2
    • 在计划相关表中有11行(仅检索6行) 来自他们的行)

  • 第3名称为:赛事#3
    • 此活动在计划中没有与其相关的任何行 相关表格

  • 第4个被叫:事件#4
    • 此事件在相关的计划中只有1行与之相关 表

我只需要检索上述3个事件和相关信息,如上所述

3 个答案:

答案 0 :(得分:2)

我只是猜测问题出在查询的OR部分。我刚刚在查询中更改了这部分:

AND ( 
ev_timetable_tt.end_date_tt > CURDATE() 
OR (ev_timetable_tt.weekday_tt = DAYNAME(CURDATE()) AND ev_timetable_tt.end_date_tt > CURDATE()) 
OR ev_timetable_tt.specific_date_tt > CURDATE()
)

可能你想这样做:(我给了别名以使其更具可读性)

SELECT * 
FROM ev_events_eve e
LEFT JOIN ev_events_multilang_evmulti eml ON eml.event_evmulti = e.id_eve
LEFT JOIN ev_schedule_sch es ON es.event_id_sch = e.id_eve
LEFT JOIN ev_events_type_et et ON es.event_type_id_sch = et.id_et
LEFT JOIN ev_events_type_multilang_etmulti emel ON emel.idevent_type_etmulti = et.id_et
LEFT JOIN ev_schedule_multilang_schmulti ems ON ems.id_schedule_schmulti = es.id_sch
LEFT JOIN ev_timetable_tt ett ON ett.schedule_id_tt = es.id_sch AND ett.event_id_tt = e.id_eve
WHERE (e.active_eve = 1 AND ems.iso_code_lang_schmulti = '{$current_language}' AND es.active_sch = 1) 
AND 
(
    ett.end_date_tt > CURDATE() 
OR (ett.weekday_tt = DAYNAME(CURDATE()) AND ett.end_date_tt > CURDATE()) 
OR ett.specific_date_tt > CURDATE()
)
ORDER BY ett.start_date_tt ASC
LIMIT 3

如果您更喜欢语法(没有表别名):

SELECT * (//instead of * i put in my code the proper columns i need from the selected tabls)
FROM 
ev_events_eve
LEFT JOIN ev_events_multilang_evmulti ON ev_events_multilang_evmulti.event_evmulti = ev_events_eve.id_eve
LEFT JOIN ev_schedule_sch ON ev_schedule_sch.event_id_sch = ev_events_eve.id_eve
LEFT JOIN ev_events_type_et ON ev_schedule_sch.event_type_id_sch = ev_events_type_et.id_et
LEFT JOIN ev_events_type_multilang_etmulti ON ev_events_type_multilang_etmulti.idevent_type_etmulti = ev_events_type_et.id_et
LEFT JOIN ev_schedule_multilang_schmulti ON ev_schedule_multilang_schmulti.id_schedule_schmulti = ev_schedule_sch.id_sch
LEFT JOIN ev_timetable_tt ON ev_timetable_tt.schedule_id_tt = ev_schedule_sch.id_sch AND ev_timetable_tt.event_id_tt = ev_events_eve.id_eve
WHERE (ev_events_eve.active_eve = 1 AND ev_schedule_multilang_schmulti.iso_code_lang_schmulti = '{$current_language}' AND ev_schedule_sch.active_sch = 1) 
AND ( 
ev_timetable_tt.end_date_tt > CURDATE() 
OR (ev_timetable_tt.weekday_tt = DAYNAME(CURDATE()) AND ev_timetable_tt.end_date_tt > CURDATE()) 
OR ev_timetable_tt.specific_date_tt > CURDATE()
)
ORDER BY ev_timetable_tt.start_date_tt ASC LIMIT 3

答案 1 :(得分:0)

LEFT JOINWHERE条件结合使用,NULL条件要求LEFT JOIN这些表格中的LEFT JOIN值无法使用WHERE 1}}。您必须在[whatever] OR NULL条件中指定值为WHERE或将ON条件指定为JOIN的{​​{1}}。

例如:

... WHERE ... (ev_schedule_sch.active_sch = 1 OR ev_schedule_sch.active_sch IS NULL) ...

或者

... LEFT JOIN ev_schedule_sch ON ev_schedule_sch.event_id_sch = ev_events_eve.id_eve AND ev_schedule_sch.active_sch = 1 ...

答案 2 :(得分:0)

首先,我也相信where子句中的日期条件应该被包装以封装它。如果不是,则应用第一部分,然后在第一个“OR”合格时完全忽略它。下一个。你有许多LEFT JOIN,这意味着只要左侧的记录合格,只有RTIONAL边表中的记录可选。但是,一旦您针对所述右侧表向WHERE子句添加条件,它就会抛出“LEFT”限定条件。您应该将该条件移动到LEFT JOIN条件而不是where子句(我已经调整过)。

您的原始查询稍微清理一下,使用别名并更正日期条件的括号,这样您就不会得到错误的结果,但是通过WHERE子句显示为隐含,将其转换为NORMAL INNER join。

SELECT *
   FROM 
      ev_events_eve EE

         LEFT JOIN ev_events_multilang_evmulti ELANG 
            ON EE.id_eve = ELANG.event_evmulti

         LEFT JOIN ev_schedule_sch SCHED 
            ON EE.id_eve = SCHED.event_id_sch

            LEFT JOIN ev_events_type_et ETYPE
               ON SCHED.event_type_id_sch = ETYPE.id_et

               LEFT JOIN ev_events_type_multilang_etmulti ETMLANG 
                  ON ETYPE.id_et = ETMLANG.idevent_type_etmulti

            LEFT JOIN ev_schedule_multilang_schmulti SMS 
               ON SCHED.id_sch = SMS.id_schedule_schmulti

            LEFT JOIN ev_timetable_tt TIMET 
               ON SCHED.id_sch  = TIMET.schedule_id_tt
              AND EE.id_eve = TIMET.event_id_tt

   WHERE 
          (   EE.active_eve = 1 
          AND SMS.iso_code_lang_schmulti = '{$current_language}' 
          AND SCHED.active_sch = 1 ) 
      AND (      TIMET.end_date_tt > CURDATE() 
            OR (    TIMET.weekday_tt = DAYNAME(CURDATE()) 
                AND TIMET.end_date_tt > CURDATE()) 
            OR TIMET.specific_date_tt > CURDATE() )
   ORDER BY 
      TIMET.start_date_tt ASC LIMIT 3

这里调整的查询是为了保持各自的LEFT JOIN,注意你的标准所在的差异。

SELECT *
   FROM 
      ev_events_eve EE

         LEFT JOIN ev_events_multilang_evmulti ELANG 
            ON EE.id_eve = ELANG.event_evmulti

         LEFT JOIN ev_schedule_sch SCHED 
            ON EE.id_eve = SCHED.event_id_sch
           AND SCHED.active_sch = 1

            LEFT JOIN ev_events_type_et ETYPE
               ON SCHED.event_type_id_sch = ETYPE.id_et

               LEFT JOIN ev_events_type_multilang_etmulti ETMLANG 
                  ON ETYPE.id_et = ETMLANG.idevent_type_etmulti

            LEFT JOIN ev_schedule_multilang_schmulti SMS 
               ON SCHED.id_sch = SMS.id_schedule_schmulti
              AND SMS.iso_code_lang_schmulti = '{$current_language}' 

            LEFT JOIN ev_timetable_tt TIMET 
               ON SCHED.id_sch  = TIMET.schedule_id_tt
              AND EE.id_eve = TIMET.event_id_tt
              AND (      TIMET.end_date_tt > CURDATE() 
                    OR (    TIMET.weekday_tt = DAYNAME( CURDATE() ) 
                        AND TIMET.end_date_tt > CURDATE() ) 
                    OR TIMET.specific_date_tt > CURDATE()    )
   WHERE 
      EE.active_eve = 1 
   ORDER BY 
      TIMET.start_date_tt ASC LIMIT 3

最后一点说明。您的ORDER BY引用了“ev_TimeTable_tt”(别名为TIMET)表,这对我来说意味着您总是期望只有在此表中可以找到明显的匹配项。如果是这样,事实上这应该是一个内部联接而不是一个左联合。

由于进入“EV_TIMETABLE_TT”表需要从计划表中查找,我希望这也是INNER JOIN要求。

因此,通过LEFT与INNER连接的澄清,您可能需要调整为这些的组合。不知道你的数据,我真的无法进一步指导。