我有一个包含有关对象信息的MySQL表。看起来像这样:
+--------------+----+--------+-------+
| auto_incr_id | id | type | value |
+--------------+----+--------+-------+
| 1 | 1 | length | 105 |
| 2 | 1 | weight | 17 |
| 3 | 1 | price | 104 |
| 4 | 2 | length | 111 |
| 5 | 2 | weight | 18 |
| 6 | 2 | price | 87 |
+--------------+----+--------+-------+
我想获取按长度排序的前x个对象:
{
"id": 2,
"length": 111,
"weight": 18,
"price": 87
},
{
"id": 1,
"length": 105,
"weight": 17,
"price": 104
}
这是我要做的事情:
首先,我获取ID:
$type = "length";
$stmt = $mysqli->prepare("SELECT id FROM table WHERE type=? ORDER BY value DESC LIMIT ?");
$stmt->bind_param('si', $type, $limit);
$stmt->execute();
$result = $stmt->get_result();
$result = $result->fetch_all(MYSQLI_ASSOC);
接下来,为获取的每个对象获取其他值:
$i = 0;
while ($i < count($result)) {
$stmt = $mysqli->prepare("SELECT type, value FROM table WHERE id=?");
$stmt->bind_param('i', $result[$i]['id']);
$stmt->execute();
$result_2 = $stmt->get_result();
$fetch = $result_2->fetch_all(MYSQLI_ASSOC);
$j = 0;
while ($j < count($fetch))
{
$result[$i][$fetch[$j]['type']] = $fetch[$j]['value'];
$j++;
}
}
例如,这对于获取前5位(
$limit = 5
)很有用,但是现在我有一个用例,我希望此信息用于前10k或更多。这花费了太多时间,可能是因为它需要经过while循环并对每个找到的ID执行一条语句。因此,我正在寻找一种减少获取此数据的执行时间的方法。有任何想法吗?
最佳答案
您的问题似乎是缺乏对表联接的理解。有一个错误和正确的方法来执行此操作。错误的方法很容易理解,因此我将向大家展示它,这样才有意义。
select id, type, value from table where id in (select id from table where type='length');
显然,这是从每个具有type ='length'值的id进行的类型/值组合。但是,您并没有在数据库中完成所有操作。您仍然必须对数据库外部的所有内容进行排序和分组。假设您只有type ='length','weight'和'price'。为此,我可以即时创建三个表格,以创建长度,重量和价格属性...
select l.id, length, weight, price from
(select id, value as length from table where type='length') l
left outer join
(select id, value as weight from table where type='weight') w
on l.id=w.id
left outer join
(select id, value as price from table where type='price') p
on l.id=p.id
order by length
现在,您将连续获得每个属性,每个id一行。 id字段在此处不能保证唯一。如果您使用相同的ID且长度不止一个,则ID将在结果中显示多次。但是,希望您能看到我如何处理明显的子查询并将其转换为联接以完成数据库内部的所有工作。
注意:我修复了歧义错误,并添加了“左外部”以包括不存在权重和价格的行。