我在我的范围内编写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”的字段值来显示其他所需的值。如果我将使用这种方式,那么我必须编写更多内部选择查询,它将减慢我的网站加载。您可以建议或建议任何其他方式来编写此查询吗?
数据库表详情:
如果您需要更详细的信息,请与我们联系。 任何帮助或建议将不胜感激。感谢。
答案 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