1

この種のことに関する同様の投稿を見たことがありますが、質問について個人的な助けが必要です.

メディア アイテムを選択すると、関連する 3 つのメディア アイテムがサイドバーに表示されるメディア サイトがあります。アイテムには、現在選択されている日付より後の日付の 2 つのアイテムと、以前の日付の 1 つのアイテムが表示されます。後の日付が 2 つない場合は、後の日付の 1 つと早い日付の 2 つだけを表示します。現在選択されているメディアがすでに最新の場合 (日付が新しい関連メディアがない場合)、日付が古い 3 つだけを表示します。もちろん、これら 3 つの結果は、現在選択されているメディアに日付が最も近い 3 つでなければなりません。

ほぼ完全に機能するクエリがあります。

    $query = "
    (SELECT
        media.*, 
        media_series.series_name, 
        media_books.book_name, 
        media_books.book_shortname  
    FROM media 
    LEFT JOIN media_series ON media.series = media_series.id
    LEFT JOIN media_books ON media.book = media_books.id 
    WHERE media.date >= '$media_date' AND media.series = '$series_id'
    AND media.id <> '$media_id_2'
    ORDER BY ABS(DATEDIFF(media.date, '$media_date')) LIMIT 2)
    UNION
    (SELECT
        media.*, 
        media_series.series_name, 
        media_books.book_name, 
        media_books.book_shortname 
    FROM media 
    LEFT JOIN media_series ON media.series = media_series.id
    LEFT JOIN media_books ON media.book = media_books.id 
    WHERE media.date <= '$media_date' AND media.series = '$series_id'
    AND media.id <> '$media_id_2'
    ORDER BY ABS(DATEDIFF(media.date, '$media_date'))) 
    ORDER BY date DESC LIMIT 3
    ";

1つ目SELECTは日付が新しい項目を最大 2 つ取得し、次に を使用しUNIONて 2 つ目SELECTは日付が早い項目を取得します。最後に、最後に、LIMIT 3全体で 3 行のみを取得するようにします。

私が見ることができるこのクエリの唯一の欠点は、現在選択されているメディアが最も古い場合 (つまり、以前の日付の関連メディアがないことを意味します)、2 つの結果のみが表示されることですSELECTSELECT.

2 番目の行が 0 行を返す場合にのみ、最初のSELECT行が 3 行を返す必要があります。SELECTどうにか使えると思っCASEていたのですが、具体的にどうすればいいのかわかりません。手伝ってくれますか?

注: 一時的な解決策として、現在クエリを実行してから、返された行数を PHP でチェックしています。3 未満の場合は、クエリ全体をもう一度実行しますがLIMIT 3、最初のSELECT. これは機能しますが、可能であれば 2 つのクエリを実行することは避けたいと思います。

ありがとう。

4

1 に答える 1

0

試す:

$query = "
SELECT * FROM
(SELECT * FROM
 (SELECT
     media.*, 
     media_series.series_name, 
     media_books.book_name, 
     media_books.book_shortname,
     @rn := @rn + 2 rn
  FROM (SELECT @rn :=-1 ) r
  CROSS JOIN media 
  LEFT JOIN media_series ON media.series = media_series.id
  LEFT JOIN media_books ON media.book = media_books.id 
  WHERE media.date >= '$media_date' AND media.series = '$series_id'
  AND media.id <> '$media_id_2'
  ORDER BY media.date LIMIT 3) sq1
 UNION ALL
 (SELECT
     media.*, 
     media_series.series_name, 
     media_books.book_name, 
     media_books.book_shortname,
     @rn := @rn + 2 rn
  FROM (SELECT @rn :=0 ) r
  CROSS JOIN media 
  LEFT JOIN media_series ON media.series = media_series.id
  LEFT JOIN media_books ON media.book = media_books.id 
  WHERE media.date < '$media_date' AND media.series = '$series_id'
  AND media.id <> '$media_id_2'
  ORDER BY media.date DESC LIMIT 3) sq2
 ORDER BY rn LIMIT 3) mq
ORDER BY date DESC
";

(1 つ目SELECT * FROMは必要ない場合があります。このクエリを SQL 経由で直接実行する場合は必要ですが、コード内に同等の行が存在しないため、別の場所で自動的に生成される可能性があります。)

ここで概念実証。

于 2013-03-22T19:28:53.573 に答える