SELECT表并从另一个表中获取一些数据(如果存在)

时间:2012-11-21 12:36:32

标签: php mysql zend-framework doctrine

任何人都可以告诉我,如果可以在Doctrine中实现以下场景(并且通常在mysql中)?

方案: 我有表cms_pages,其字段如下:

  
      
  • ID
  •   
  • cms_languages_id
  •   
  • 名称
  •   
  • 含量
  •   
  • 别名
  •   

另一个名为cms_pages_translations的表格,其中包含以下字段:

  
      
  • ID
  •   
  • cms_pages_id(外键)
  •   
  • cms_languages_id
  •   
  • 名称
  •   
  • 含量
  •   
  • 别名
  •   

现在,就是说,那个

 $language_id = 2;

我正在查询cms_pages并看到,cms_pages.cms_languages_id不等于$ language_id ...(所以我的页面内容不是我正在寻找的语言)。但没关系。我们得到了一个名为cms_pages_translations的表,其中应该存在翻译。所以我想在同一个查询中从cms_pages_translations获取匹配的值(名称,内容,别名),如果有记录

cms_languages_id == $language_id.

我希望很清楚我想要实现的目标:)

因此查询输出数据将包含:

  
      
  • id(来自cms_pages)
  •   
  • name(来自cms_pages_translations)
  •   
  • 内容(来自cms_pages_translations)
  •   
  • 别名(来自cms_pages_translations)
  •   

3 个答案:

答案 0 :(得分:0)

如果cms_pages_id是cms_pages.id的外键,那么为什么不在cms_pages_translations中查询,因为此表中应包含所有翻译。我认为你应该有$ page_id来获得任何特定的页面翻译。

您可以使用以下查询

SELECT id, NAME, content, alias FROM cms_pages WHERE id=1 AND cms_languages_id = 2
UNION
SELECT cms_pages_id, NAME, content, alias FROM cms_pages_translations WHERE cms_pages_id=1 AND cms_languages_id = 2 AND 0 = (SELECT COUNT(id) FROM cms_pages WHERE id=1 AND cms_languages_id = 2);

但是这会再次针对每种情况扫描cms_pages_translations。最好的事情是fire 2查询条件(如注释中所述)并在cms_pages_translations上创建一个索引(cms_pages_id,cms_languages_id)

答案 1 :(得分:0)

您可以尝试IFNULL构造,例如:

SELECT IFNULL(
    (SELECT content FROM cms_pages WHERE cms_languages_id=3 AND id=1), 
    (SELECT content FROM cms_pages_translations WHERE cms_languages_id=3 AND id=1)
  )

唯一的一点就是,IFNULL一次只能回溯一列。所以你可以分别查询每个列。

或者你尝试这样的JOIN

SELECT *
FROM cms_pages_translations t 
JOIN cms_pages p ON p.id=t.cms_pages_id
WHERE t.id=1 AND (t.cms_languages_id=1 OR p.cms_languages_id=1)

如果存在,将返回两个表的所有字段。假设“name”,“alias”和“content”的数据只出现在两个表中的一个表中,那么就可以执行此操作。

答案 2 :(得分:0)

您可以尝试使用MySQL Case。我记得它不能直接在Zend中使用,所以我将它与Zend_Db_Expr一起使用。

public function getPageTranslated($page_id, $language_id) {
    $name = new Zend_Db_Expr("
        CASE 
            WHEN p.language_id = $language_id THEN p.name
            ELSE pt.name
        END
    ");

    $content = new Zend_Db_Expr("
        CASE 
            WHEN p.language_id = $language_id THEN p.content
            ELSE pt.content
        END
    ");

    $alias = new Zend_Db_Expr("
        CASE 
            WHEN p.language_id = $language_id THEN p.alias
            ELSE pt.alias
        END
    ");

    $select = $this->select()
            ->from(array('p' => 'cms_pages'), array('id' => 'p.id', 'name' => $name, 'content' => $content, 'alias' => $alias))
            ->where('p.id = ?', $page_id)
            ->joinLeft(array('pt' => 'cms_pages_translations'), 'p.id = pt.cms_pages_id', array('pt.name', 'pt.content', 'pt.alias'))
            ->where('pt.language_id = ?', $language_id)
            ->limit(1)
            ->setIntegrityCheck(false);

    $result = $this->fetchAll($select);

    return $result? $result->toArray(): false;
}