充分利用单个 MySQL 查询
Posted
技术标签:
【中文标题】充分利用单个 MySQL 查询【英文标题】:Getting the most from a single MySQL query 【发布时间】:2012-11-13 19:42:07 【问题描述】:我有一个网站,列出了可供出租的公寓。我的 mysql 数据库中有几个不同的表。一张表格是关于整个公寓楼的基本信息,包括地址、便利设施、照片、身份证 (NID) 等。
另一个表格列出了每栋建筑内可供出租的单元。所以每栋公寓楼都有多个平面图,有几个工作室、几个一居室单元,有时还有几个二居室单元等。
目前我查询我的“单元”表并询问给定公寓楼中的所有单元。我的查询类似于SELECT * FROM node_unit WHERE nid='555'
这可能会返回如下内容:
NID Name Rent SqFT Bedrooms Bathrooms
555 Unit 1 $500 620 0 1
555 Unit 2 $550 680 0 1
555 Unit 3 $600 820 1 1
555 Unit 4 $650 920 1 1
555 Unit 5 $700 1220 2 1
555 Unit 6 $800 1420 2 2
555 Unit 7 $900 1500 3 2
555 Unit 8 $1100 1620 3 3
等等等等
然后我在我的 php 中做的是使用手风琴将 1 间卧室组合在一起,将 2 间卧室组合在一起,等等。
并非所有公寓都有 2 个卧室单元,有些只有 1 个卧室单元,所以我需要在我的 PHP 代码中知道是否应该打印另一个手风琴。
目前我正在对数据库进行多次点击来确定给定的建筑物是否有任何 2 个卧室单元,如果有,则打印另一行。这栋楼有三居室单位吗?如果是这样打印另一行,但我想停止这么多访问我的数据库。
最后,这是我的问题:
如何存储我的第一个 DB 调用的结果并以某种方式解析数据并确定给定的 NID 是否有工作室、1 张床、2 张床等? (我最近才开始学习PHP/MySQL)
【问题讨论】:
请发布您当前的脚本,否则很难提出建议。 只要结果卷不超过特定大小限制,您就可以检索结果中的所有条目并将它们简单地存储在 php 数组中。然后,您将拥有世界上所有的时间来完成并提取您需要的任何信息。不过,不确定这是否更快...... 【参考方案1】:我建议这样的查询:
SELECT * FROM node_unit WHERE nid='555'
ORDER BY Bedrooms ASC, Bathrooms ASC, Rent ASC
这将返回您按卧室数、# 间浴室和租金金额(按此顺序)排序的记录。
当像这样从数据库读取时,您可以轻松地将其存储在多维数组中(假设 mysqli
与存储在 $result
中的结果集一起使用,但其他数据库连接库的概念相同)
$room_array = array();
while ($row = mysqli_fetch_assoc($result))
$room_array[(int)$row['Bedrooms']][] = $row;
您现在有一个以卧室数作为第一个索引的多维数组。如果你var_dump
它,数组可能看起来像这样:
Array (
[0] => Array (
[0] => Array (
'NID' => '555',
'Name' => 'Unit 1',
'Rent' => '$500',
'SqFt' => '620',
'Bedrooms' => '0',
'Bathrooms' => '1',
)
[1] => Array (
'NID' => '555',
'Name' => 'Unit 2',
'Rent' => '$550',
'SqFt' => '680',
'Bedrooms' => '0',
'Bathrooms' => '1',
)
)
[1] => Array (
[0] => Array (
'NID' => '555',
'Name' => 'Unit 3',
'Rent' => '$600',
'SqFt' => '820',
'Bedrooms' => '1',
'Bathrooms' => '1',
)
[1] => Array (
'NID' => '555',
'Name' => 'Unit 4',
'Rent' => '$650',
'SqFt' => '920',
'Bedrooms' => '1',
'Bathrooms' => '1',
)
[2] => Array (
...
)
[3] => Array (
...
)
)
这使得在外部循环中迭代卧室值的数量变得非常容易,这会创建您的手风琴,然后在内部循环中迭代各个房间。
foreach ($room_array as $num_bedrooms => $rooms)
// start accordion
foreach ($rooms as $room)
// output room details
// end accordion
所有这些都只需要一个查询。
还要确保你有关于卧室、浴室、租金(或你在排序中使用的任何一个)以及 nid 的索引,因为它被用作过滤器。
【讨论】:
感谢您的帮助。这似乎是一个很好的方法。使用您的代码,我能够设置一个数组,然后在 foreach 中使用 print_r 我可以看到该数组正在正确设置数据。在我的最后,卧室是第 5 个索引,而不是第一个,我不确定这是否重要。不过我想知道,既然数据在一个数组中,我怎样才能只抓住 1 间卧室或 2 间卧室?您列出的 foreach 示例循环通过,但我想将项目分组到手风琴中。我确定我只是缺少一些简单的东西。我可以说“如果索引 [5] = “3” 那么... 我想通了,只是需要另一个循环:if ($room['5'] == 0) echo "studios"; if ($room['5'] == 1) echo "1 bedrooms";
您一定没有按照我提到的方式设置阵列。如果按照我提到的方式完成,我添加了一个 var_dump 的示例。数组的第一级代表一组卧室数量。第一维索引为 0 的所有东西都有 0 个卧室,索引为 1 的所有东西都有一个卧室,依此类推。【参考方案2】:
尝试将此作为您的数据库查询,它会为每个建筑物为其拥有的每种单元类型生成一行。您还可以将其用作子查询并连接到父表,以便一次性获取有关建筑物的任何其他详细信息。
select 'studio' as unit_type, nid from node_unit group by nid having count(case when bedrooms = 0 then 1 end) > 0
union all
select 'one bedroom' as unit_type, nid from node_unit group by nid having count(case when bedrooms = 1 then 1 end) > 0
union all
select 'two bedroom' as unit_type, nid from node_unit group by nid having count(case when bedrooms = 2 then 1 end) > 0
union all
select 'three bedroom' as unit_type, nid from node_unit group by nid having count(case when bedrooms = 3 then 1 end) > 0
【讨论】:
这将是一个非常低效的查询。如果您希望将字符串值作为单位类型返回,则最好采用我的答案中显示的查询并将 case 语句放入 SELECT 中,例如SELECT nid, name, rent, sqft, (CASE WHEN bedrooms = 0 THEN 'studio' WHEN bedrooms = 1 THEN 'one_bedroom' WHEN bedrooms = 2 THEN 'two bedrooms' WHEN bedrooms = 3 THEN 'three bedrooms' END CASE) as unit_type, bedrooms, bathrooms FROM node_unit WHERE nid='555' ORDER BY bedrooms ASC, bathrooms ASC, rent ASC
当然,您的建议更有效,但它不会为每个建筑物和房间组合生成新行,以便轻松绑定到 Jay 所追求的 UI。有很多方法可以生成相同的结果集,而无需在桌面上进行四次传递,但根据观众,我认为太高级是不合适的。以上是关于充分利用单个 MySQL 查询的主要内容,如果未能解决你的问题,请参考以下文章