1

我在我的范围内编写 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 [以及更多字段]]

如果您需要更多详细信息来获得此问题,请告诉我。任何帮助或建议将不胜感激。谢谢。

4

2 回答 2

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

但我不确定性能,以及这个解决方案是否是最优的。

于 2013-02-18T13:11:29.193 回答
0

正如另一个人所问的那样,但你没有对每场演出的“结束时间”做出回应,我不得不假设演出时间是开始的时间。也就是说,您如何根据 CURTIME()(而不是固定时间值)确定给定频道的当前节目正在运行。

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

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

所以,如果我有 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 点开始),下一个节目是当前时间之后的第一个节目(节目“Y”从下午 2:30 开始)。即使行不是按顺序排列的,上述方法也可以工作,因为我分别使用 MIN() 和 MAX() 来获取时间。

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

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

所以现在,我已经准备好所有内容,并准备好使用各自的内容别名。现在,我只是抓住我想要呈现的列。

由于连接都是 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
于 2013-02-18T13:55:50.550 回答