如何在连续的表格中显示其他表格数据?
我有以下MySQL的方案:如何在连续的表格中显示其他表格数据?
Method table: PK id, name, comment
Okp table: PK id, FK method_id, comment
Tnved table: PK id, FK method_id, comment
Okp --many to one--> Method <-- many to one-- Tnved
图像表示:
我需要从方法显示HTML汇总表。但是每个方法(每行)都可以有来自其他表格的许多数据,我需要将它们全部显示出来。
它看起来像这样:
Methods summary
+-----+-----------+--------------+---------------+-----+---------+
| id | name | All OKP data | All TNVED data| ... | Comment |
+-----+-----------+--------------+---------------+-----+---------+
| 1 | Cloth 1 | 841000 | 5007000000 | ... | Special |
| | | 842000 | 5111000000 | | |
| | | 843000 | 5112000000 | | |
| | | 844000 | ... much more | | |
| | | ...much more | | | |
+-----+-----------+--------------+---------------+-----+---------+
| 2 | Game 76 | 259000 | 6100000000 | ... | Nice |
| | | 816700 | 6200000000 | | |
| | | 880000 | 6400000000 | | |
| | | ...much more | ...much more | | |
+-----+-----------+--------------+---------------+-----+---------+
| ... | ... | ... | ... | | ... |
+-----+-----------+--------------+---------------+-----+---------+
| 999 | T-shirt 3 | 831701 | 6302600000 | ... | Bad |
+-----+-----------+--------------+---------------+-----+---------+
我tryed使用SQL JOIN,但它看起来无情无义具有多重冗余。所以我不知道如何更好地使用查询。
我用PHP解决了这个问题,通过单独的查询接收每行的相关数据,但是这个解决方案太慢了。 (实际上我有1000多行)。
那么如何查询和显示这些数据呢?
我用下面的方法来从数据库获取信息:
//Model-file pseudo-code
$result = array();
$methods = $this->db
->select('*')
->from('method')
->get()
->result();
$i = 0;
foreach ($methods as $method){
$result[$i]['method_t'] = $method;
$result[$i]['okps'] = $this->db
->select('*')
->from('okp')
->where('method_id', $method['id]')
->get()
->result();
$result[$i]['tnveds'] = $this->db
->select('*')
->from('tnved')
->where('method_id', $method['id]')
->get()
->result();
//so on
$i++;
}
我用下面的方法来显示汇总表:
//View-file pseudo-code
//Table header
foreach ($result as $method) {
echo '<tr>';
echo '<td>' . $method['method_t']['id'] . '</td>';
echo '<td>' . $method['method_t']['name'] . '</td>';
echo '<td><ul>';
foreach ($method['okps'] as $okp) {
echo '<li>' . $okp['id'] . '</li>';
//in fact much more data from $okp with separate template
}
echo '</ul></td>';
echo '<td><ul>';
foreach ($method['tnveds'] as $tnved) {
echo '<li>' . $tnved['id'] . '</li>';
}
//in fact much more data from $tnveds with separate template
echo '</ul></td>';
//so on
echo '</tr>';
}
echo '</table>';
也许我失去了一些东西,由于我的缺乏PHP技能,但我没有看到为什么你无法一次性获得所有记录,然后只是使用php来显示它的方式。下面是一个例子,但我与它缺乏经验的PHP只能被描述为伪代码:
select
m.id as m_id,
m.name as m_name,
m.comment as m_comment,
o.id as o_id,
o.comment as o_comment,
t.id as t_id,
t.comment as t_comment
from
method m
inner join okp o
on m.id = o.method_id
inner join tnved t
on m.id = t.method_id
order by m.id, o.id, t.id;
的PHP,像下面这样。我省略了tvned的东西,因为您可以通过复制okp部分的模型来添加它。
$is_first=true;
$m_id_last = 0;
$m_id = 0;
$o_id_last = 0;
$o_id = 0;
$o_str = "";
foreach ($result as $method) {
$m_id_last = $m_id;
$m_id = $method['m_id'];
if ((!is_first) && ($m_id_last != $m_id)) {
echo '<tr>';
echo '<td>' . $m_id . '</td>';
echo '<td>' . $method['name'] . '</td>';
echo '<td><ul>';
echo o_str;
echo '</ul></td>';
echo '</tr>';
$o_str = "";
}
$o_str .= '<li>' . $method['o_id'] . '</li>';
$is_first=false;
}
为什么不使用单个SQL查询,但在使用INNER JOIN
时要小心。 因为您可以在okp表中具有方法1相关行,但在表表中没有任何方法#1的行,反之亦然。下面我用名列,而不是为OKP和tnved表评论列的查询和PHP代码:
当心。
因此,SQL应该是水木清华这样的:
SELECT m.id, o.id AS oid, o.name AS oname, t.id AS tid, t.name as tname, m.comment
FROM
(method AS m LEFT JOIN okp AS o ON m.id = o.method_id)
LEFT JOIN tnved AS t ON m.id = t.method_id
ORDER BY m.id
查询执行后上面你就会有水木清华这样的: https://drive.google.com/a/thepaydock.com/file/d/0B3C0Ywfdde5Fa2lPc0FBdlZENG8/view?usp=drivesdk
下一个迭代查询结果与PHP行:
$output = array();
foreach($results AS $id => $method) {
$output[$id]['okps'] = array();
$output[$id]['tnveds'] = array();
if(!is_null($method['oid'])) {
$output[$id]['okps'][$method['oid']] = array(
'name' => $method['oname'];
);
};
if(!is_null($method['tid'])) {
$output[$id]['tnveds'][$method['tid']] = array(
'name' => $method['tname'];
);
}
}
Next render $output
array其中$output
array key is method_id。
上面的php代码也可以重构。我提供了一个基本的例子。
基本问题是半笛卡尔产品。如果“okp”(对于给定的m_id)有五行,而“tnved”有六行,则连接操作将与来自“okp”的每行匹配来自“tnved”的每行,共有三十行。每个“okp”行的6份副本,每个“tnved”行的5份副本。
如果在连接中涉及三个,四个,五个表格,并且每个表格都有十几个或更多行......那么由此产生的复制集合变得笨拙。
有几种方法可以解决这个问题。
如果我要运行针对“方法”的查询,并从一个循环,一个“M_ID”在同一时间处理每一行...
对于从“方法”的每一行,我会执行另一个查询来从“okp”,“tnved”等中取回所有行。通过将单个查询与UNION ALL相结合。这将消除行的重复。通过适当的索引例如“...在okp(m_id,id)”上,查询应该非常高效。
例如:
SELECT okp.m_id AS m_id
, 'okp' AS src
, okp.id AS id
, okp.comment AS comment
FROM okp
WHERE okp.m_id = ?
ORDER BY okp.m_id, okp.id
UNION ALL
SELECT tnved.m_id AS m_id
, 'tnved' AS src
, tnved.id AS id
, tnved.comment AS comment
WHERE tnved.m_id = ?
ORDER BY tnved.m_id, tnved.id
我们使用UNION ALL而不是UNION,所以结果只是连接到一起,并避免排序和去除重复行的开销。
请注意,我们包含一个“src”鉴别器列。我们的代码可以使用此列中的值来确定哪个查询返回了它。在这种情况下,每个查询都来自单个表,因此我们可以识别这些值来自哪个表。
如果其中一个表比其他查询有更多的列要返回,我们将“dummy”表达式添加到其他查询的SELECT列表中。这可以让我们满足UNION ALL的要求,其中所有组合的集合必须具有相同数量的列和相同的数据类型。
这种方法消除了我们用半笛卡尔产品获得的大量重复。这种方法需要对我们处理的每个m_id进行“额外”查询,但是如果我们只在页面上放置20个m_id,则只有20个查询要运行。
只要php为此...执行查询,为每个绑定占位符提供m_id值。获取结果,并将每行放入适当的(清空)数组中。从“okc”到$ okc []数组的行,从“tnved”到$ tnved []数组中的行。
看起来这样的设置可以用于当前的“输出”代码。
只要你处理M_ID的数量有限,而且有可用的合适的索引,这种方法可能是相当有效的。
循环中的基本“控制中断”处理...按m的顺序处理行。如果当前行为相同的m(this m_id = previous m_id),则跳过输出有关新m的信息。当我们有一个新的m时,只输出有关m的信息。这是一种常见的方法。 (我还没有深入到答案中提供的php。)+10。 – spencer7593