0

我有一个由 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、徽标、标语、开始和结束日期)
      • 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_ttev_schedule_sch通过外键关联

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

  • 第一个被称为:事件#1
    • 此事件在时间表相关表中有 3 行(因此检索
      所有这些行)


  • 第二个被称为:事件#2
    • 这在计划相关表中有 11 行(仅从中检索 6 行)

  • 第三个被称为:事件#3
    • 此事件在日程相关表中没有任何与其相关的行

  • 第 4 个被称为:事件#4
    • 此事件在日程相关表中只有 1 行与之相关

如上所述,我只需要检索日程表中的前 3 个事件和相关事件

4

3 回答 3

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
于 2012-04-22T12:27:00.127 回答
0

LEFT JOINs 与需要在ed的那些表中WHERE的非值的条件结合使用,违背了使用 a 的目的。您要么必须在条件中指定值可以是,要么使条件成为.NULLLEFT JOINLEFT JOINWHERE[whatever] OR NULLWHEREONJOIN

例如:

... 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 ...
于 2012-04-22T12:38:40.583 回答
0

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

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

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)表,这对我来说意味着您总是希望在此表中只找到明确的匹配项。如果是这样,这实际上应该是 INNER JOIN 而不是 LEFT JOIN。

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

因此,随着 LEFT vs INNER join 的澄清,您可能需要调整这些组合。不知道你的数据,我真的无法进一步指导。

于 2012-04-22T13:06:43.743 回答