2015-12-21 57 views
0

我有一个游戏,文章(评论+预览)和视频(视频评论+视频预览)的数据库。我有一个ID为233的游戏,如果这些游戏存在,我想查找一个评论,一个预览,一个视频评论和视频预览。MYSQL和PHP:没有结果的SELECT子查询返回空值数组键

要做到这一点,我使用下面的查询:

SELECT (SELECT article_url 
     FROM articles 
     WHERE articles_game_id = 233 
       AND artikel_sort = 'review' 
       AND article_online = 1 
     ORDER BY article_datetime DESC 
     LIMIT 1) AS review, 

     (SELECT article_url 
     FROM articles 
     WHERE articles_game_id = 233 
       AND artikel_sort = 'preview' 
       AND article_online = 1 
     ORDER BY article_datetime DESC 
     LIMIT 1) AS preview, 

     (SELECT trailer_url 
     FROM trailers 
     WHERE trailer_game_id = 233 
       AND trailer_sort = 'video review' 
       AND trailer_online = 1 
     ORDER BY trailer_datetime DESC 
     LIMIT 1) AS videoreview, 

     (SELECT trailer_url 
     FROM trailers 
     WHERE trailer_game_id = 233 
       AND trailer_sort = 'video preview' 
       AND trailer_online = 1 
     ORDER BY trailer_datetime DESC 
     LIMIT 1) AS videopreview 
FROM articles 

然而,这个查询有两个问题:

  • 它查询数据库的五倍,这似乎不是很有效对我来说。
  • 如果没有评论(例如),生成的PHP数组确实有一个键/值对与键'review',但其值为空。但是,我希望此键/值对完全不存在,因此我可以简单地遍历数组并将每个键/值对打印为链接。

有没有人知道解决这个问题的有效方法?任何帮助是极大的赞赏!

+0

由于'ORDER BY trailer_datetime DESC LIMIT 1',左连接将不会生成正确的记录 –

+0

您确定在这里遇到效率问题吗?数据库擅长查询,如果它被称为很多(如果它不是很多,那么它的速度有多快?),通常会在幕后优化这些东西。你有证据证明你的应用程序实际上在这个查询上花了很多时间吗? – DaveyDaveDave

回答

2

不幸的是,这似乎是一个任务,你不能逃脱使用单独的查询。但是,我会使用union来合并查询的结果,而不是联接,或者选择列表中的子查询或单独的查询。

  1. 随着工会有
  2. 如果工会查询不返回任何行,那么就不会在结果(见OP需求)的客户端和数据库之间只有1个往返。请注意,type字段的值会告诉您返回的网址的类型。

示例代码:

SELECT article_url, 'review' as type 
     FROM articles 
     WHERE articles_game_id = 233 
       AND artikel_sort = 'review' 
       AND article_online = 1 
     ORDER BY article_datetime DESC 
     LIMIT 1 
UNION ALL 
SELECT article_url, 'preview' 
     FROM articles 
     WHERE articles_game_id = 233 
       AND artikel_sort = 'preview' 
       AND article_online = 1 
     ORDER BY article_datetime DESC 
     LIMIT 1 
UNION ALL 
SELECT trailer_url, 'video review' 
     FROM trailers 
     WHERE trailer_game_id = 233 
       AND trailer_sort = 'video review' 
       AND trailer_online = 1 
     ORDER BY trailer_datetime DESC 
     LIMIT 1 
UNION ALL 
SELECT trailer_url, 'video preview' 
     FROM trailers 
     WHERE trailer_game_id = 233 
       AND trailer_sort = 'video preview' 
       AND trailer_online = 1 
     ORDER BY trailer_datetime DESC 
     LIMIT 1 

另一种解决方案是使用子查询来获取最大日期(或ID,如果文章/拖车ID是auto_increment的字段)。但是,您需要2个子查询(1或者文章,1个预告片),然后是2个查询,其中子查询连接到文章/预告表,第5个顶部将它们组合成1个查询,所以我不会描述这种方法。

+0

这里唯一的缺点是不是执行一个PDO'fetch'(这会导致单个数组看起来像'Array('review'=>'review_url','preview'=>'preview_url')',我有执行'fetchAll',这会导致嵌套数组看起来像'Array([0] => Array([url] =>'review_url',[type] =>'review'),[1] => Array ([url] =>'preview_url',[type] =>'preview')etc.'有没有办法保持原有的数组结构? –

+0

除非你还原回原来的查询。这应该是4的第一个。 – Shadow