MySQL - 如何根据返回的行数使我的查询有条件?

时间:2013-03-22 18:43:15

标签: mysql select union rows

我已经看过类似的帖子,但是我想要个人帮助查询。

我们所拥有的是一个媒体网站,当选择媒体项目时,它会在侧边栏中显示三个相关的媒体项目。这些项目应显示两个具有较晚日期的项目,一个具有比当前所选日期更早的日期。如果没有两个日期较晚,则只显示一个日期较晚且两个日期较早的日期。如果当前选择的媒体已经是最新的(没有相关媒体以及更晚的日期),那么只需显示具有较早日期的三个媒体。当然,这三个结果必须是与当前所选媒体最接近的三个结果。

我的查询几乎完美无缺:

    $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确保我们只能获得三行。

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

只有当第二个SELECT返回零行时,我才需要第一个SELECT返回3行。我以为我可以用某种方式使用CASE,但我不确定究竟是多少。你能帮忙吗?

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

感谢。

1 个答案:

答案 0 :(得分: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运行此查询,但代码中的等效行不存在,那么它可能会在其他位置自动生成。)

概念证明here