【问题标题】:How to build one virtual table with its heading coming from others table's values如何构建一个虚拟表,其标题来自其他表的值
【发布时间】:2019-05-16 13:03:46
【问题描述】:

我有 2 个表格,其中插入是由于填写表格。第一个表,称为 data,用 id 注册一行。另一个名为 data_entry 的表注册了几行:表单中的每个字段一个。对于 3 个条目,它给出了类似的内容:

第一张桌子:

data

id
__
1
2
3

第二张桌子:

data_entry

data_id    name     value
_____________________________________
1          name     John
1          age      35
1          email    j.smith@smith.com
2          name     Alex
2          age      20
2          email    alex@dot.com
3          name     Kenny
3          age      18
3          email    ken62@ggl.com

我的需要

我想在如下表中显示一些数据,仅通过 SQL 请求

id    name     email
________________________________
1     John     j.smith@smith.com
2     Alex     alex@dot.com
3     Kenny    ken62@ggl.com

我的临时解决方案

我用一些 PHP 构建我的表,并在一个循环中进行了许多查询,但我想这不是最漂亮(和优化)的解决方案:

$tab = array(); // the table I create
$entries = $this->db->query('SELECT id FROM data'); // the form entries

// for each entry, I create the row in my table
foreach ($entries as $entry) {
    // I search for the 3 lines according to the same ID
    $query = $this->db->query('SELECT name, value FROM data_entry WHERE data_id = ' . $entry->id );
    $line = array('id' => $entry->id);

    foreach ($query->result() as $row) { // I build my table's row with each result, except the age not needed
        switch ($row->name) {
        case 'name':
            $line['name'] = $row->value;
            break;
        case 'email':
            $line['email'] = $row->value;
            break;
        default:
            break;
        }
    }
// now I can build the row in the table
$tab[$entry->id] = $line;
}

有没有更好的方法来获得相同的结果,只使用 SQL,或者只使用一个请求和一点 PHP?

【问题讨论】:

    标签: php sql arrays


    【解决方案1】:

    你可以这样做,请参考内联文档进行解释

    $query = $this->db->query("SELECT data_id, GROUP_CONCAT(CONCAT(name,'=', value) SEPARATOR '@@@') nv   
    FROM data_entry where name in ('name','email') GROUP BY data_id");
    
    echo "<table><tr> <th>id</th> <th>name</th> <th>email</th> </tr>";
    foreach ($query as $k => $v) {
        $temp = explode("@@@", $v->nv); // I have used double separator(inter row level)
        echo "<tr> <td> " . $v->data_id . "</td>";
        foreach ($temp as $v1) {
            list($name, $value) = explode("=",$v1); // same row level
            echo "<td>$value</td>";
        }
        echo "</tr>";
    }
    echo "</table>";
    

    Group_CONCAT() 函数。 MySQL 中的 GROUP_CONCAT() 函数是 用于将多行的数据连接到一个字段中。这是个 聚合 (GROUP BY) 函数,它返回一个字符串值,如果 group 至少包含一个非 NULL 值。否则,它返回 空。

    list — 像数组一样分配变量

    【讨论】:

    • 有趣的方式,我第一次看到 GROUP_CONCAT 的使用,它确实有效!如果我找不到 100% SQL 解决方案,我将使用它。非常感谢 ;) PS:当我谈到创建表时,实际上我只需要获取一个包含数组(用于行)的数组(将是表)。我有一个函数可以创建我的 HTML 表格。
    【解决方案2】:

    我认为这就是你所需要的。

    SELECT id, name, VALUE
      FROM (SELECT DATA_ENTRY.ID,
                   (CASE
                        WHEN data_entry.NAME = 'name' THEN data_entry.VALUE
                        ELSE NULL
                    END)
                       name,
                   (CASE
                        WHEN data_entry.NAME = 'email' THEN data_entry.VALUE
                        ELSE NULL
                    END)
                       email
              FROM data INNER JOIN data_entry ON (data.id = data_entry.data_id))
     WHERE name IS NOT NULL AND VALUE IS NOT NULL
    
    

    【讨论】:

    • 这很聪明!!但是每一行总是至少有一个 NULL 字段,所以最后的结果总是空的。我会尝试使用 NULL 字段来操作临时表,我感觉解决方案不远了。
    • 我做到了,谢谢你!!我将您的临时表更改为 2 个表,一个带有(id,name),另一个带有(id,email)。然后我在这两个表之间进行了连接,条件是避免名称和电子邮件上的 NULL 值。我将发布解决方案的明确代码。再次感谢你:)
    • 太棒了。我为你感到高兴:)
    【解决方案3】:

    感谢@F.Lazarescu 的回复,展示我找到的解决方案:

    SELECT tp1.id, name, email FROM (
    
    SELECT data_entry.data_id id,
                   (CASE
                        WHEN data_entry.name = 'name' THEN data_entry.value
                        ELSE NULL
                    END)
                       name
              FROM data INNER JOIN data_entry ON data.id = data_entry.data_id
    ) tp1 
    JOIN
    (SELECT data_entry.data_ID id,
                   (CASE
                        WHEN data_entry.name = 'email' THEN data_entry.value
                        ELSE NULL
                    END)
                       email
              FROM data INNER JOIN data_entry ON data.id = data_entry.data_id
    ) tp2
    ON tp1.id = tp2.id
    WHERE
    tp1.name IS NOT NULL
    AND
    tp2.email IS NOT NULL
    

    结果就像我想要的一样(并且快 50 倍):

    id    name     email
    ________________________________
    1     John     j.smith@smith.com
    2     Alex     alex@dot.com
    3     Kenny    ken62@ggl.com
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-13
      • 2012-10-26
      • 2023-02-13
      • 1970-01-01
      相关资源
      最近更新 更多