【问题标题】:ignore duplicate results from foreach loop iterating through mysql query忽略foreach循环遍历mysql查询的重复结果
【发布时间】:2011-12-02 05:13:53
【问题描述】:

我设置了一个多选表单来返回数组,然后通过mysql查询循环它们以返回结果

如果用户选择多个选项并且那些 选项在一个记录中

例如,用户选择了三个不同的“视图”,一个属性具有所有三个视图,我不想在结果中显示三次...谢谢您的帮助

    require ('db.php');

    $N = $_GET['Neigh'];
   $V = $_GET['view'];
   $C = $_GET['Con'];
  $F = $_GET['front'];
 $minPrice = $_GET['minprice'];
 $maxPrice = $_GET['maxprice'];
 $Year = $_GET['YearBuilt'];



   foreach($N as $Nvalue){
   if ($Nvalue != "\n\r" || $Nvalue != "" || $Nvalue !=NULL)
   foreach($C as $Cvalue){
   foreach($F as $Fvalue){
   foreach($V as $Vvalue){

   $query="SELECT *
   FROM `foo`
   WHERE `Building` LIKE '%{$Bvalue}%' && `Neigh` = '{$Nvalue}' && `View` 
   LIKE  '%{$Vvalue}%' && `Con` LIKE '%{$Cvalue}%'
   && `front` LIKE '%{$Fvalue}%' && `Listprice` BETWEEN '{$minprice}' AND '{$maxprice}' 
   && `Year_Built` >= '{$Year}' && `Status` LIKE '%Active%' GROUP BY `MLS` 
  ORDER BY `Neigh`, `price`, `tmk` ASC";

  $result=mysql_query($query) or die('Query failed: ' . mysql_error() . "<br />\n $query"); ;

  $num=mysql_num_rows($result);

对不起,如果这是一团糟..我是从互联网上自学的..它确实有效,但在同一记录中返回多个变量的重复项...

【问题讨论】:

标签: php mysql arrays foreach


【解决方案1】:

SELECT * FROM foo WHERE Building LIKE ... && Neighborhood = .... && View 喜欢 ... && Condition 喜欢 ... && Frontage 喜欢 ... Listprice 介于 ... && Year_Built >= ... && Status 喜欢 ...

如果我没记错的话,这个查询表明你有一个包含上述所有属性的表。

至少查看多值属性的气味。如果在同一个表中找到它,那么它是一个非常经典的冗余数据示例。因此,如果您对一所房子有三个视图,您最终将存储同一建筑物的 3 条记录。

这里出现了一些问题:

  1. 你的标识符有多可靠,有多正确。
  2. 如果你有 2000 个房子,其中一半有 2 个视图,你最终会 在同一个表中还有 1000 多条记录。
  3. 删除或更新有多容易
  4. 查询的一致性如何(我认为这是您的问题所在) 等等

如果这是真的,那么 99% 的情况下您不会在工作环境中进行任何更改,但是最好知道系统中的流量是什么,以便您采取措施。

在理想情况下,您处于构建阶段,仍处于开发阶段,那么对于多个值的每个属性,您需要使用构建表的外键将字段单独传输到新表。

如果用户选择多个视图,您可以这样查询:

select some_fields 
from building 
left join on views 
where view = view1 or view2 etc

这个查询不能带多条记录,因为没有这样的东西, 每个建筑物只定义一次,带有明确的标识符(主键) 归一化的结果,在建表中!另一方面,视图中的多个记录将有助于捕获记录(如果有任何或所有视图 匹配)。

最后看到 4 个循环在一起通常是强烈警告代码需要认真优化!

我也同意,你现在可以选择 distinct!

【讨论】:

  • 非常感谢。我尝试使用 distinct,但我想将不同的记录带回 1 列,一个唯一的 id,但 distinct 不允许我携带我需要填写下面的结果表的所有信息。我将尝试多表建议。谢谢
  • 只是为了澄清..所有视图都存储在我的桌子上,就像这座山、海洋、码头排成一排..我不确定加入是否会有所作为,但我会尝试...... @Melsi
  • 虽然您选择了要返回的字段,并对字段值设置条件,但您必须记住,没有像引入唯一不同的字段这样的事情。这是因为我们对行进行查询,我们的对象始终是行,所以当你想到不同的时候,你必须考虑记录行。考虑显示一个 sql 转储或一些关于您的表的描述以及一些业务规则(您知道数据库应该做什么),这将有很大帮助,否则继续有问题的数据库模式没有太大帮助。
  • 每一行都有一个唯一的 id # .. 我想如果我可以让它不重复那个数字它只会返回 1 条记录而不是重复但不知道该怎么做.. 我真的很感激你所有的帮助
【解决方案2】:

如果您想将当前设计与视图存储在单个单元格中,那么您可以做一些事情。虽然我不建议这样做,但我在下面给出一个示例,因为您已经设计了这样的项目。

注意:这是一个测试示例,用于查看基本功能。这不是最终代码,因为 sql 注入和其他事情没有考虑到。

我假设视图存储在单个单元格中,以空格分隔,如果视图包含多个单词 - 则位于两者之间,例如 City-Center。

研究这个例子,看看你是否可以根据你的需要调整它:

<?PHP
echo '<pre>';

//mysql connect
mysql_connect('localhost', 'root',''); 
mysql_select_db("test"); 
//add some tsting data
addTestingData();

//build sql from user input via $_GET   
$sqlConditions = builtSql();//build sql conditions
$sql = 'select * from `building` where '.$sqlConditions;//build final sql

//get data from mysql
$result  = mysql_query($sql )  ; 
while($row=   mysql_fetch_row($result) ) 
    print_r( $row );

///////////////end//////////////////////////////////////////// 

function addTestingData()
{

mysql_query("DROP TABLE IF EXISTS `Building`");
     mysql_query("
CREATE TABLE `Building` (
  `building_uniqueid` MEDIUMINT UNSIGNED NOT NULL  , 
  `building_street` VARCHAR(30) NOT NULL,
  `building_street_nr` VARCHAR(7) NOT NULL,  
  `building_neighborhood` VARCHAR(30) NOT NULL,  
  `building_view` VARCHAR(250) NOT NULL, 
  `building_condition` VARCHAR(150) NOT NULL,  
  `building_frontage` VARCHAR(30) NOT NULL,
  `building_listprice` float NOT NULL, 
  `building_year` smallint not null,  
  `bsnss_comments` VARCHAR(255), 
  PRIMARY KEY  (`building_uniqueid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
"); 

     mysql_query('
insert into `building` (`building_uniqueid`,`building_street`,`building_street_nr`,
`building_neighborhood`,`building_view`,`building_condition`,`building_frontage`,
`building_listprice`,`building_year`,`bsnss_comments`) values 
("1","street1","strnr1","neighb1","Mountain Ocean Lake Park City-Center",
"good","frontage1","500.3","1990","good building")
'); 

     mysql_query('
insert into `building` (`building_uniqueid`,`building_street`,`building_street_nr`,
`building_neighborhood`,`building_view`,`building_condition`,`building_frontage`,
`building_listprice`,`building_year`,`bsnss_comments`) values 
("id2","street1","strnr1","neighb2","River Ocean Lake Park City-Center",
"very good","frontage1","800.5","1991","good building")
') or die(mysql_error()); 

     mysql_query('
insert into `building` (`building_uniqueid`,`building_street`,`building_street_nr`,
`building_neighborhood`,`building_view`,`building_condition`,`building_frontage`,
`building_listprice`,`building_year`,`bsnss_comments`) values 
("3","street3","strnr3","neighb1","Ocean Park City-Center",
"fantastic","frontage77","600.7","1994","good building")
'); 

     mysql_query('
insert into `building` (`building_uniqueid`,`building_street`,`building_street_nr`,
`building_neighborhood`,`building_view`,`building_condition`,`building_frontage`,
`building_listprice`,`building_year`,`bsnss_comments`) values 
("4","street4","strnr4","neighb1","Ocean Park Mountain City-Center",
"good","frontage1","500.23","1994","good")
'); 

  $_GET['Neighborhood']=array('neighb1');
  $_GET['View']=Array('Mountain','River', 'City Center');
  $_GET['Condition']=array('good','very good');
  $_GET['Frontage']=array('frontage77','frontage1');
  $_GET['minPrice']='500';
  $_GET['maxPrice']='600';
  $_GET['minYear']='1990';
  $_GET['maxYear']='1995';



}



function builtSql()
{

  $sqlBuild = '( ';

//formate sql for Neighborhood
foreach($_GET['Neighborhood'] as $value)
    $sqlBuild .=' `building_neighborhood` = \''.$value.'\' or ';   
    $sqlBuild=removeLastOr($sqlBuild);
    $sqlBuild.=') and (';

//formate sql for View
foreach($_GET['View'] as $value) 
    $sqlBuild .=' `building_view` LIKE \'%'.str_replace(" ", "-",$value).'%\' or ';   
    $sqlBuild=removeLastOr($sqlBuild);
    $sqlBuild.=') and (';

 //formate sql for Condition
foreach($_GET['Condition'] as $value) 
    $sqlBuild .=' `building_condition` = \''.$value.'\' or ';   
    $sqlBuild=removeLastOr($sqlBuild);
    $sqlBuild.=') and (';

 //formate sql for Frontage
foreach($_GET['Frontage'] as $value) 
    $sqlBuild .=' `building_frontage` = \''.$value.'\' or ';   
    $sqlBuild=removeLastOr($sqlBuild);
    $sqlBuild.=') and (';

 //formate sql for Price
$sqlBuild.=
' `building_listprice` BETWEEN \''.$_GET['minPrice'].'\' and \''.$_GET['maxPrice'].'\'   ';
    $sqlBuild=removeLastOr($sqlBuild);
    $sqlBuild.=') and (';

//formate sql for Year
$sqlBuild.=
' `building_year` BETWEEN \''.$_GET['minYear'].'\' and \''.$_GET['maxYear'].'\' '; 
    $sqlBuild.=')  ';

return $sqlBuild;
}

function removeLastOr($str)
{
    $tmp=substr($str ,0,(strlen($str )-2));
    return $tmp=substr($str ,0,(strlen($str )-3)); 
}

?>

虽然你看到了一些 foreach 循环,但不必担心,因为它们会针对包含用户数据的小数组运行,因此请考虑它们运行速度超快,因为不涉及 mysql 查询!

如果仍有任何问题,请考虑提供有关 db 架构的详细信息和一些基本描述。希望这能有所帮助!

【讨论】:

  • 非常感谢..我现在要试试这个..@Melsi
  • 我遇到了很多错误......我修复了一个然后我得到了另一个所以我今晚晚些时候会回来
  • 我建议你先自己运行代码,没有错误,这就是我把所有东西都放在那里的原因,以便它立即运行并且独立地,只需为 mysql connect 输入正确的信息。在您完全了解它如何独立工作之前,不要继续将其合并到您的应用程序中。如果您理解它,那么将它合并到您的应用程序应该没有问题。最后,您当前的数据库架构是什么,获取一个 sql 转储,(现在对我来说太晚了,要睡觉了)
  • ,, 谢谢你所做的一切。我让它工作了。我非常感谢你所做的一切。
  • 我很高兴听到这个消息!不要忘记至少使用 mysql_real_escape_string 进行 sql 注入。删除最终代码上的任何 die 函数,..or die(mysql_error()) 是开发时的保护程序,但不能在生产中使用!而是把 mysql_query() 或 my_err_handle();这是你自己做的事情。如果有空闲时间我建议作为下一个目标:学习 RedBean ORM 和 Entity-Relationship 等(关系模型)设计。
猜你喜欢
  • 2021-02-15
  • 1970-01-01
  • 1970-01-01
  • 2015-05-09
  • 1970-01-01
  • 2015-10-05
  • 1970-01-01
  • 2021-09-06
  • 1970-01-01
相关资源
最近更新 更多