需要帮助来制作一个mysql查询以获得我的要求的预期结果

时间:2013-02-18 05:43:03

标签: mysql join multi-select

我在我的范围内编写mysql查询以获得结果时遇到的问题很少。实际上我使用这个现有的查询获得了适当的结果,但它没有以适当的方式编写。这是我的疑问:

    SELECT c.ID, c.chn_name,c.chn_logo, 
    (SELECT ID FROM tv_showtime WHERE showtime<='2013-02-18 10:28:35' AND status='Enable' AND chn_id=c.ID ORDER BY ID DESC Limit 0,1) as currentshowid, 
    (SELECT tv_showtime FROM tv_showtime WHERE showtime<='2013-02-18 10:28:35' AND status='Enable' AND chn_id=c.ID ORDER BY ID DESC Limit 0,1) as currentshowtime , 
    (SELECT tv_showtime FROM tv_showtime WHERE showtime >'2013-02-18 10:28:35' AND status='Enable' AND chn_id=c.ID ORDER BY ID ASC Limit 0,1) as nextshowtime 
    FROM tv_channels AS c 
    WHERE c.status="Enable" 
    ORDER BY c.chn_name 
    LIMIT 0,10

这里只有两个名为“tv_channels”和“tv_showtime”的表。我一次需要一个记录(当前时间)。因此,这里假设每个频道有12个频道和大约30个频道(可能会改变每个频道的每个频道),我只需要显示当前节目的频道(更多说明:将只显示具有当前节目时间和/或下一个节目时间的频道。 )

问题:我需要更多来自“tv_showtime”的字段值来显示其他所需的值。如果我将使用这种方式,那么我必须编写更多内部选择查询,它将减慢我的网站加载。您可以建议或建议任何其他方式来编写此查询吗?

数据库表详情:

  • tv_channels [ID,chn_name,[其他必填字段]],
  • tv_showtime [ID,chn_id,showtime,show_name,hits,last_ip [以及更多字段]]

如果您需要更详细的信息,请与我们联系。 任何帮助或建议将不胜感激。感谢。

2 个答案:

答案 0 :(得分:0)

要按某种顺序从表中选择最后(第一个)记录,您可以LEFT JOIN将表格作为任何下一个(上一个)元素,并添加条件没有这样的元素。

SELECT c.ID, c.chn_name, c.chn_logo
  , curr_sh.ID AS currentshowid, curr_sh.showtime AS currentshowtime -- Continue with desired columns
  , next_sh.showtime AS nextshowtime -- Continue with desired columns
  FROM tv_channels AS c 
    LEFT JOIN tv_showtime AS curr_sh
      ON curr_sh.chn_id = c.ID
        AND curr_sh.showtime <= '2013-02-18 10:28:35'
        AND curr_sh.status='Enable'
    LEFT JOIN tv_showtime AS curr_next_sh
      ON curr_next_sh.chn_id = curr_sh.chn_id
        AND curr_next_sh.showtime >  curr_sh.showtime
        AND curr_next_sh.showtime <= '2013-02-18 10:28:35'
        AND curr_next_sh.status = 'Enable'
    LEFT JOIN tv_showtime AS next_sh
      ON next_sh.chn_id = c.ID
        AND next_sh.showtime > '2013-02-18 10:28:35'
        AND next_sh.status='Enable'
    LEFT JOIN tv_showtime AS next_prev_sh
      ON next_prev_sh.chn_id = next_sh.chn_id
        AND next_prev_sh.showtime <  next_sh.showtime
        AND next_prev_sh.showtime > '2013-02-18 10:28:35'
        AND next_prev_sh.status = 'Enable'
  WHERE c.status = 'Enable'
    AND curr_next_sh.ID IS NULL -- This gives us only the latest current show
    AND next_prev_sh.ID IS NULL -- This gives us only the earliest next show
    AND (curr_sh.ID IS NOT NULL OR next_sh.ID IS NOT NULL) -- This gives us 'which has current show time and/or next show time'
  ORDER BY c.chn_name 
  LIMIT 0,10

但我不确定性能,以及此解决方案是否最佳。

答案 1 :(得分:0)

正如另一个人所问,但你没有回应每个节目的“结束时间”,我不得不继续前提,即节目开始的时间。也就是说,如何根据CURTIME()(而不是固定时间值)确定给定通道的当前节目运行情况。

获取每个频道和MAXIMUM SHOW在当前时间之前存在的时间......

同样,如何获得NEXT Show?获取每个频道的MINIMUM SHOW时间,即当前时间之后的STARTS。

所以,如果我有1个频道的以下记录,当前时间是下午2:15

Channel   ShowTime   Show_Name
1         12:30pm    Show "X"
1         01:00pm    Show "B"
1         01:30pm    Show "C"     
1         02:00pm    Show "D"      <-  Current Show
1         02:30pm    Show "Y"      <-  Next Show
1         03:00pm    Show "Z"

当前节目的运行是最早的2:15(显示“D”从下午2点开始) NEXT Show是当前时间之后的第一个(显示“Y”,从下午2:30开始)。即使行不按顺序排列,上面也会有效,因为我分别使用MIN()和MAX()来获取时间。

因此,我从频道表开始,对每个单独的预聚合查询进行左连接,分别检测当前节目和下一个节目时间,并加入频道ID,每个COULD最多返回一条记录 - - 如果在合格的WHERE CURTIME()考虑范围内有一条记录。

从那时起,我将这些结果集重新加入实际的电视节目表AGAIN,但这一次,在频道上以及与相应的当前或下次匹配的时间。

所以现在,我已经准备好了所有内容准备与内容相应的别名。现在,我只是抓住我想要呈现的列。

由于连接都是LEFT-JOIN,因此每一侧都可以有NULL值,因此您可能需要调整查询以使用COALESCE()来防止空值,例如我已经采样...

SELECT
      TC.ID,
      TC.Chn_Name,
      TC.Chn_Logo,
      COALESCE( CurShowTimeDetail.ShowTime, 'no time' )  CurShowTime,
      COALESCE( CurShowTimeDetail.Show_Name, '' )        CurShowName,
      COALESCE( CurShowTimeDetail.Hits, 0 )              CurHits,
      COALESCE( NextShowTimeDetail.ShowTime, 'no time' ) NextShowTime,
      COALESCE( NextShowTimeDetail.Show_Name, '' )       NextShowName,
      COALESCE( NextShowTimeDetail.Hits, 0 )             NextHits
   from 
      TV_Channels TC

         LEFT JOIN ( SELECT 
                           ST.chn_id, 
                           MAX( ST.showtime ) CurShowTime
                        from
                           tv_showtime ST
                        where
                           ST.ShowTime < CURTIME()
                        group by
                           ST.chn_id ) CurrentShow
            ON TC.ID = CurrentShow.Chn_ID
            LEFT JOIN tv_showtime CurShowTimeDetail
               ON CurrentShow.Chn_ID = CurShowTimeDetail.Chn_ID
               AND CurrentShow.CurShowTime = CurShowTimeDetail.ShowTime

         LEFT JOIN ( SELECT 
                           ST.chn_id, 
                           MIN( ST.showtime ) NextShowTime
                        from
                           tv_showtime ST
                        where
                           ST.ShowTime > CURTIME()
                        group by
                           ST.chn_id ) NextShow
            ON TC.ID = NextShow.Chn_ID
            LEFT JOIN tv_showtime NextShowTimeDetail
               ON NextShow.Chn_ID = NextShowTimeDetail.Chn_ID
               AND NextShow.NextShowTime = NextShowTimeDetail.ShowTime