动态列名称取决于查询结果的单行

时间:2013-11-26 09:33:45

标签: php mysql

我在sql查询中需要一些动态列名的帮助。首先,我将尝试解释我的数据库结构,然后解决问题。

数据库结构:

admin_group表:

+--------+----------------+
| id     | language_code  |
+--------+----------------+
| 1      | en_UK          | 
| 2      | de_DE          | 
| 3      | es_ES          |
+--------+----------------+

constructions_meta table:

+--------+-----------------+----------+
| id     | admin_group_FK  | value    |
+--------+-----------------+----------+
| 1      | 1               | 0.13     |
| 2      | 2               | 0.12     |
| 3      | 3               | 0.10     |
+--------+-----------------+----------+

construction_lang table:

+--------+-----------------+----------------+----------------+
| id     | en_UK_name      | de_DE_name     |es_ES_name      |
+--------+-----------------+----------------+----------------+
| 1      | Construction 1  | Konstruktion 1 | Construcción 1 |       
| 2      | Construction 2  | Konstruktion 2 | Construcción 2 |  
| 3      | Construction 3  | Konstruktion 3 | Construcción 3 |  
+--------+-----------------+----------------+----------------+

这些是我在数据库中的表。我需要的是获取有关每个构造的语言代码的结构的名称。例如,我想列出如下构造:

  1. 建筑1
  2. Konstruktion 2
  3. Construcción3

3 个答案:

答案 0 :(得分:3)

select c.id , (select case c.admin_group_FK 
                when 1 then l.en_UK_name 
                when 2 then  l.de_DE_name 
                else l.es_ES_name 
          end from construction_lang l where id = c.id) as construction_name,
    c.value
from constructions_meta c;

是的,解决方案只是一个让你快速工作的解决方案。 Rob对改进数据模型是正确的

解决方案是:

您需要从数据模型中删除constru_lang表,并将其替换为此关联表,就像Rob提出的那样

+------------------+--------------+----------------+
| construction_fk  | language_fk  |    name        |
+------------------+--------------+----------------+
| 1                | 1            | Construction 1 |
| 1                | 2            | Konstruktion 1 |
| 1                | 3            | Construcción 1 |
| 2                | 1            | Construction 2 |
| 2                | 2            | Konstruktion 2 |
| 2                | 3            | Construcción 2 |
| 3                | 1            | Construction 3 |
| 3                | 2            | Konstruktion 3 |
| 3                | 3            | Construcción 3 |   
+------------------+--------------+----------------+

然后查询你需要的是

select c.id, l.language_code ,  a.name ,c.value
from constructions_meta c
join construction_lang_assoc a on a.construction_fk = c.id and a.language_fk = c.admin_group_FK 
join admin_group l on l.id = c.admin_group_FK;

答案 1 :(得分:2)

两次传球可能最容易做到这一点。这将使您能够扩展construction_lang表的宽度,而不会显着影响SQL语句。

首先发出一个SQL语句来获取所需的列名,然后使用该结果集构建第二个SQL语句,为您获取名称。

这不是理想的解决方案,因为它正在围绕数据模型。

给出一个返回admin_group的id和语言的查询:

array( array( 'id' => 1, 'language_code' => 'en_UK' ),
       array( 'id' => 2, 'language_code' => 'de_DE' ),
       array( 'id' => 3, 'language_code' => 'es_ES' ) )

你可以用一些东西来构建一个陈述(使用diarmuid的另一个答案作为例子)

$sql = "select c.id , (select case c.admin_group_FK\r\n";
foreach( $languages as $thisLanguage ) {
   $sql .= "when {$thisLanguage['id']} then l.${thisLanguage['language_code']}_name\r\n";
}
$sql .= ...

由于您拥有的数据模型,这是一种全面的方式。理想情况下,您不需要“动态”SQL。“

如果你想删除round-about-ness,并且构建更符合标准关系数据库理论的东西,那么你可以改变模型,使constru_lang表更像这样:

+------------------------+-----------------+----------------+
| constructions_meta_fk  | language        | name           |
+------------------------+-----------------+----------------+
| 1                      | en_UK           | Construction 1 |
| 1                      | de_DE           | Konstruktion 1 |
| 1                      | es_ES           | Construcción 1 |
| 2                      | en_UK           | Construction 2 |
| 2                      | de_DE           | Konstruktion 2 |
| 2                      | es_ES           | Construcción 2 |
| 3                      | en_UK           | Construction 3 |
| 3                      | de_DE           | Konstruktion 3 |
| 3                      | es_ES           | Construcción 3 |
+------------------------+-----------------+----------------+

答案 2 :(得分:-2)

你可以使用if条件`

if(admin_group_FK == 1)
{
fetch['en_UK_name'];
}
if(admin_group_FK == 2)
{
fetch['de_DE_name'];
}
if(admin_group_FK == 3)
{
fetch['es_ES_name'];
}

`