MySQL - 我怎样才能使我的查询条件基于它会返回的行数?

标签 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 确保我们总共只得到三行。

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

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

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

谢谢。

最佳答案

尝试:

$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 .

关于MySQL - 我怎样才能使我的查询条件基于它会返回的行数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15577662/

相关文章:

php - 如何使用多主机连接到mysql服务器?

MySQL 对元素进行分组并计算每组中的元素数

mysql - 合并 1 列并选择其他

MySQL 通过使用连接查询来优化联合查询

MySQL:在 1:N 关系中哪个更快?加入或两个查询?

mysql - 非对象上的bind_param

SQLITE:如果第一列为空,则选择另一列

javascript - 如何默认选择列表不选择与 jQuery bsmSelect 插件一起使用的元素

MySQL - 按总 LIMIT 选择 UNION 中每个的等量

mysql - iOS - mySQL (apache) 和 iOS (NSDate) 之间时间戳的正确格式