1

我看过关于这种事情的类似帖子,但我想要个人帮助我的查询。

What we have is a media site that, when a media item is selected, displays three related media items in a sidebar. 这些项目应显示两个项目的日期较晚,一个项目的日期早于当前选择的项目。如果没有两个较晚的日期,则只显示一个较晚的日期和两个较早的日期。如果当前选择的媒体已经是最新的(没有较晚日期的相关媒体),则只显示较早日期的三个。当然,这三个结果需要是与当前选择的媒体日期最接近的三个。

我有一个几乎可以完美运行的查询:

    $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
    ";

第一个SELECT获得最多两个具有较晚日期的项目,然后,使用UNION,第二个SELECT获得具有较早日期的任何项目。最后,最后的LIMIT 3确保我们总共只得到三行。

我能看到的这个查询的唯一缺陷是,如果当前选择的媒体是最旧的(意味着它没有更早日期的相关媒体),那么只会显示两个结果,因为第一个SELECT限制为 2,第二个SELECT不返回任何结果.

只有当第二个返回零行时,我才需要第一个SELECT返回 3行。SELECT我在想我可以CASE以某种方式使用,但我不确定具体如何。你能帮我吗?

注意:作为临时解决方案,我目前正在运行查询,然后使用 PHP 检查返回的行数,如果小于 3,我将再次运行整个查询,但LIMIT 3在第一个SELECT. 这可行,但我想尽可能避免运行这两个查询。

谢谢。

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
";

(第一个SELECT * FROM可能不是必需的 - 如果直接通过 SQL 运行此查询,但代码中的等效行不存在,因此它可能会在其他地方自动生成。)

这里的概念证明。

于 2013-03-22T19:28:53.573 回答