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」という名前のテーブルが 2 つだけあります。一度に各チャネルに 1 つのレコードが必要です (現在の時間)。したがって、ここでは、12 のチャンネルと、各チャンネルに約 30 (チャンネルごとに異なる場合があります) のレコードがあり、現在の番組のチャンネルのみを表示する必要があるとします (より明確にするために、現在の番組時間および/または次の番組時間を持つチャンネルのみが表示されます。 )

問題: 他の必要な値を表示するには、「tv_showtime」のフィールド値がさらに必要です。この方法を使用する場合は、内部選択クエリをさらに作成する必要があり、Web サイトの読み込みが遅くなります。このクエリを書くための他の方法を提案またはアドバイスできますか?

データベース テーブルの詳細:

  • 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() に基づいて、特定のチャンネルで実行中の現在のショーをどのように判断しますか。

各チャンネルと、現在の時刻より前に存在する最大ショー時間を取得します...

同様に、NEXT 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() を使用しているため、行が連続していなくても機能します。

そのため、チャンネル テーブルから開始し、現在のショーと次のショーの時間をそれぞれ検出するために、個別の事前集計クエリに左結合を実行し、それぞれが最大で 1 つのレコードを返す可能性のあるチャネル ID で結合します --- そこにある場合修飾された WHERE CURTIME() 考慮事項内のレコードです。

それから、THOSE の結果セットを実際の TV スケジュール テーブルに再度結合していますが、今回は、対応する現在または次回に一致するチャンネルと時刻で行います。

これで、コンテンツのそれぞれのエイリアスを使用する準備が整いました。ここで、表示する列を取得します。

結合はすべて LEFT-JOIN であるため、各側に NULL 値が含まれる可能性があるため、クエリを調整して COALESCE() を使用して null を防止することをお勧めします。

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 に答える