MySQL 结果的下拉选项分组
Option Grouping in Drop-Down from MySQL results
我正在尝试为下拉选择表单创建选项组,但我在 $innerRow = mysqli_fetch_array($innerResults)
行收到以下错误。
Warning: mysqli_fetch_array() expects parameter 1 to be mysqli_result,
boolean given
代码
$options = "";
$query = "SELECT DISTINCT manufacturer_name
FROM product p
JOIN manufacturer m
ON p.manufacturer_id = m.manufacturer_id";
$outerResults = mysqli_query($con, $query);
while ($outerRow = mysqli_fetch_array($outerResults)) {
$options .= "<optgroup label='{$outerRow["manufacturer_name"]}'>";
$query = "SELECT product_id, model_number
FROM product
WHERE manufacturer_id
IN (SELECT manufacturer_id
FROM manufacturer
WHERE manufacturer_name = {$outerRow["manufacturer_name"]}";
$innerResults = mysqli_query($con, $query);
while ($innerRow = mysqli_fetch_array($innerResults)) {
$options .= "<option value='{$innerRow["product_id"]}'>{$innerRow["model_number"]}</option>";
}
mysqli_free_result($innerOptions);
}
mysqli_free_result($outerOptions);
mysqli_close($con)
首先,您的内部查询失败的原因是因为您没有按照字符串值的要求将 {$outerRow["manufacturer_name"]}
括在单引号中,并且您没有关闭子查询的括号:'{$outerRow["manufacturer_name"]}');
但是我不想让您修复查询,请继续阅读...
关于您的流程,我想更正一些地方:
- 您的第一个查询没有利用
MySQL
的真正威力。您真的不应该对数据库中的每个制造商进行新查询——这样效率很低。
- 我建议您声明查询的结果集并对其进行条件检查,以避免出现警告消息并适当地处理错误的查询。
- 您没有在 dom 构建期间关闭
<optgroup>
标签。您的输出仍将按需要呈现,但标签将被关闭。
- 因为您没有使用结果集中的数字键,所以您应该使用
mysqli_fetch_assoc()
而不是 mysqli_fetch_array()
。
这是对您的代码的完全重写,它将进行上述更正并将您的查询过程精简为单个调用:
require_once("db.php");
$sql="SELECT M.manufacturer_name,P.product_id,P.model_number
FROM manufacturer M
LEFT JOIN product P ON M.manufacturer_id=P.manufacturer_id
GROUP BY M.manufacturer_id,P.product_id
ORDER BY M.manufacturer_name,P.model_number;";
if($result=mysqli_query($con,$sql)){
if(mysqli_num_rows($result)){
$last_group=null;
$select="<select name=\"products\">";
while($row=mysqli_fetch_assoc($result)){
if($row["manufacturer_name"]!=$last_group){
$select.=($last_group!=null?"</optgroup>":"")."<optgroup label=\"{$row["manufacturer_name"]}\">";
$last_group=$row["manufacturer_name"];
}
if($row["product_id"]==null){
$select.="<option disabled>No Products</option>";
}else{
$select.="<option value=\"{$row["product_id"]}\">{$row["model_number"]}</option>";
}
}
$select.="</optgroup></select>";
echo $select;
mysqli_free_result($result);
}else{
echo "Empty Resultset From Query";
}
}else{
echo mysqli_error($con);
}
我使用这些 table 结构和数据测试了上面的代码:
CREATE TABLE `product` (
`product_id` int(10) NOT NULL,
`manufacturer_id` varchar(20) NOT NULL,
`model_number` varchar(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `product` (`product_id`, `manufacturer_id`, `model_number`) VALUES
(1, '1', '#0001'),
(2, '1', '#0002'),
(3, '1', '#0003'),
(4, '2', '#0001'),
(5, '2', '#0002'),
(6, '4', '#0001');
ALTER TABLE `product`
ADD PRIMARY KEY (`product_id`);
ALTER TABLE `product`
MODIFY `product_id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
和
CREATE TABLE `manufacturer` (
`manufacturer_id` int(10) NOT NULL,
`manufacturer_name` varchar(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `manufacturer` (`manufacturer_id`, `manufacturer_name`) VALUES
(1, 'AAAA'),
(2, 'BBBB'),
(3, 'CCCC'),
(4, 'DDDD');
ALTER TABLE `manufacturer`
ADD PRIMARY KEY (`manufacturer_id`);
ALTER TABLE `manufacturer`
MODIFY `manufacturer_id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
我的代码块将输出这个:
<select name="products">
<optgroup label="AAAA">
<option value="1">#0001</option>
<option value="2">#0002</option>
<option value="3">#0003</option>
</optgroup>
<optgroup label="BBBB">
<option value="4">#0001</option>
<option value="5">#0002</option>
</optgroup>
<optgroup label="CCCC">
<option disabled>No Products</option>
</optgroup>
<optgroup label="DDDD">
<option value="6">#0001</option>
</optgroup>
</select>
呈现为:
p.s。如果您不希望结果集(或 select 选项列表)中出现无产品制造商,请在 GROUP BY
和 ORDER BY
lines/clauses 之间写入 HAVING P.product_id IS NOT NULL
。
我正在尝试为下拉选择表单创建选项组,但我在 $innerRow = mysqli_fetch_array($innerResults)
行收到以下错误。
Warning: mysqli_fetch_array() expects parameter 1 to be mysqli_result, boolean given
代码
$options = "";
$query = "SELECT DISTINCT manufacturer_name
FROM product p
JOIN manufacturer m
ON p.manufacturer_id = m.manufacturer_id";
$outerResults = mysqli_query($con, $query);
while ($outerRow = mysqli_fetch_array($outerResults)) {
$options .= "<optgroup label='{$outerRow["manufacturer_name"]}'>";
$query = "SELECT product_id, model_number
FROM product
WHERE manufacturer_id
IN (SELECT manufacturer_id
FROM manufacturer
WHERE manufacturer_name = {$outerRow["manufacturer_name"]}";
$innerResults = mysqli_query($con, $query);
while ($innerRow = mysqli_fetch_array($innerResults)) {
$options .= "<option value='{$innerRow["product_id"]}'>{$innerRow["model_number"]}</option>";
}
mysqli_free_result($innerOptions);
}
mysqli_free_result($outerOptions);
mysqli_close($con)
首先,您的内部查询失败的原因是因为您没有按照字符串值的要求将 {$outerRow["manufacturer_name"]}
括在单引号中,并且您没有关闭子查询的括号:'{$outerRow["manufacturer_name"]}');
但是我不想让您修复查询,请继续阅读...
关于您的流程,我想更正一些地方:
- 您的第一个查询没有利用
MySQL
的真正威力。您真的不应该对数据库中的每个制造商进行新查询——这样效率很低。 - 我建议您声明查询的结果集并对其进行条件检查,以避免出现警告消息并适当地处理错误的查询。
- 您没有在 dom 构建期间关闭
<optgroup>
标签。您的输出仍将按需要呈现,但标签将被关闭。 - 因为您没有使用结果集中的数字键,所以您应该使用
mysqli_fetch_assoc()
而不是mysqli_fetch_array()
。
这是对您的代码的完全重写,它将进行上述更正并将您的查询过程精简为单个调用:
require_once("db.php");
$sql="SELECT M.manufacturer_name,P.product_id,P.model_number
FROM manufacturer M
LEFT JOIN product P ON M.manufacturer_id=P.manufacturer_id
GROUP BY M.manufacturer_id,P.product_id
ORDER BY M.manufacturer_name,P.model_number;";
if($result=mysqli_query($con,$sql)){
if(mysqli_num_rows($result)){
$last_group=null;
$select="<select name=\"products\">";
while($row=mysqli_fetch_assoc($result)){
if($row["manufacturer_name"]!=$last_group){
$select.=($last_group!=null?"</optgroup>":"")."<optgroup label=\"{$row["manufacturer_name"]}\">";
$last_group=$row["manufacturer_name"];
}
if($row["product_id"]==null){
$select.="<option disabled>No Products</option>";
}else{
$select.="<option value=\"{$row["product_id"]}\">{$row["model_number"]}</option>";
}
}
$select.="</optgroup></select>";
echo $select;
mysqli_free_result($result);
}else{
echo "Empty Resultset From Query";
}
}else{
echo mysqli_error($con);
}
我使用这些 table 结构和数据测试了上面的代码:
CREATE TABLE `product` (
`product_id` int(10) NOT NULL,
`manufacturer_id` varchar(20) NOT NULL,
`model_number` varchar(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `product` (`product_id`, `manufacturer_id`, `model_number`) VALUES
(1, '1', '#0001'),
(2, '1', '#0002'),
(3, '1', '#0003'),
(4, '2', '#0001'),
(5, '2', '#0002'),
(6, '4', '#0001');
ALTER TABLE `product`
ADD PRIMARY KEY (`product_id`);
ALTER TABLE `product`
MODIFY `product_id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
和
CREATE TABLE `manufacturer` (
`manufacturer_id` int(10) NOT NULL,
`manufacturer_name` varchar(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `manufacturer` (`manufacturer_id`, `manufacturer_name`) VALUES
(1, 'AAAA'),
(2, 'BBBB'),
(3, 'CCCC'),
(4, 'DDDD');
ALTER TABLE `manufacturer`
ADD PRIMARY KEY (`manufacturer_id`);
ALTER TABLE `manufacturer`
MODIFY `manufacturer_id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
我的代码块将输出这个:
<select name="products">
<optgroup label="AAAA">
<option value="1">#0001</option>
<option value="2">#0002</option>
<option value="3">#0003</option>
</optgroup>
<optgroup label="BBBB">
<option value="4">#0001</option>
<option value="5">#0002</option>
</optgroup>
<optgroup label="CCCC">
<option disabled>No Products</option>
</optgroup>
<optgroup label="DDDD">
<option value="6">#0001</option>
</optgroup>
</select>
呈现为:
p.s。如果您不希望结果集(或 select 选项列表)中出现无产品制造商,请在 GROUP BY
和 ORDER BY
lines/clauses 之间写入 HAVING P.product_id IS NOT NULL
。