【问题标题】:SELECT query for multiple checkbox in HTML (PHP, Postgresql)SELECT查询HTML中的多个复选框(PHP,Postgresql)
【发布时间】:2016-01-25 16:36:29
【问题描述】:

我需要进行 动态 SQL 查询,该查询从 DB 中返回几列,具体取决于复选框 html 表单中检查的数据。在这段代码中,它只返回被检查的最后一列数据不是全部。我只能考虑检查所有与 IF 子句的组合,但由于实际上我有比 3 更多的复选框,我想知道是否有人可以提出一些动态解决方案。

<?php
// Connecting to a Postgresql DB
...
// Values sent from HTML form
$checked = $_POST["check_list"];
$submit = $_POST["submit"];
?>

<form action="" method="POST">  
Choose:
<input type="checkbox" name="check_list[]" value="5"> 5h    
<input type="checkbox" name="check_list[]" value="6"> 6h    
<input type="checkbox" name="check_list[]" value="7"> 7h    
<br><br>    
<input type="submit" name="submit">
</form>

 <?php
// Checking if something is checked
// If it is do something
if(isset($submit)){
    if(empty($checked)){
        echo "Please choose something";     
    } else {        
        foreach($checked as $selected){
            // Adding 0 in front of one dimensional numbers because of DB column name
            if ($selected < 10){
                $selected = "0$selected";
            }
            $db_colum_name = "a_b$selected";

            $query = "SELECT table1. name,
                             table1. latitude / CAST(10 AS FLOAT(6)) AS lat,
                             table1. longitude / CAST(10 AS FLOAT(6)) AS lng,
                             EXTRACT(YEAR FROM table2. date) AS year,
                             table2. $db_colum_name AS $selected
                     FROM table1
                     JOIN table2 
                     ON table1.id=table2.id
                     WHERE
                     name = 'New York'
                     AND
                     EXTRACT(YEAR FROM table2. date) = '2000'
                     ORDER BY date DESC";

            $result = pg_query($dbcon, $query) or die("Your error: {$query} <br>");
        }

        // Printing data
        ...
        // Closing DB connection
        pg_close ($dbcon);

    }
}
?>

编辑:

某种架构:

表 1

标识 |姓名 |纬度 |经度 |
5 |纽约| 40.7 | -74.00 |

表 2

标识 |日期 | a_b05 | a_b06 | a_b07 |
5 |2000-03-02 | 100 | 105 | 200 |

【问题讨论】:

  • 为此处涉及的表共享您的 SQL 数据库架构?我可以告诉你你的问题是每个 foreach 都会覆盖你的结果变量。您应该设计 SQL 语句,以便每个 foreach 添加到它,然后在迭代后执行查询。

标签: php sql postgresql select checkbox


【解决方案1】:

你可以做的是有一个字符串,它为循环的每次迭代附加一个字符串,该循环将被添加到查询字符串中。

$stringBuilder .= ", table2.$db_colum_name as $selected";

另一件事是将查询移到循环之外,以便它只获取一次结果,而不是每次迭代。然后您可以将$stringBuilder 附加到查询中

 $query = "SELECT table1. name,
        table1. latitude / CAST(10 AS FLOAT(6)) AS lat,
        table1. longitude / CAST(10 AS FLOAT(6)) AS lng,
        EXTRACT(YEAR FROM table2. date) AS year
        $stringBuilder

毕竟它看起来像这样:

$stringBuilder = "";
foreach($checked as $selected){
    // Adding 0 in front of one dimensional numbers because of DB column name
    if ($selected < 10){
        $selected = "0$selected";
    }
    $db_colum_name = "a_b$selected";
    $stringBuilder .= ", table2.$db_colum_name as $selected";
}

$query = "SELECT table1. name,
        table1. latitude / CAST(10 AS FLOAT(6)) AS lat,
        table1. longitude / CAST(10 AS FLOAT(6)) AS lng,
        EXTRACT(YEAR FROM table2. date) AS year
        $stringBuilder
    FROM table1
    JOIN table2 
    ON table1.id=table2.id
    WHERE
    name = 'New York'
    AND
    EXTRACT(YEAR FROM table2. date) = '2000'
    ORDER BY date DESC";

$result = pg_query($dbcon, $query) or die("Error: {$query} <br>");

希望这会有所帮助!

【讨论】:

  • 这东西有效!非常好的解决方案!谢谢!起初我在查询中在 $stringBuilder 之前留下了逗号,所以我遇到了一些问题,但现在这很有效!
  • 没问题,很高兴它有帮助! :)
【解决方案2】:

您使用的方案不是最优的。研究数据库规范化,它既有助于将来对数据进行校对,也有助于更轻松地编写强大的 SQL 查询。

如果想要的输出是这样的:

name      lat                lng   a_b05_year  a_b05  a_b06_year  a_b06  a_b07_year  a_b07  
New York  4.070000076293946  -7.4  2000        100    2000        105    2000        200   

那么这个查询应该用你当前的模式来解决问题:

$array = array('5', '6', '7'); //Simulated checkbox return. In '' because they're strings not integers

$select = "SELECT table1.name, table1.latitude / CAST(10 AS FLOAT(6)) AS lat, table1.longitude / CAST(10 AS FLOAT(6)) AS lng,";
$q = "";

$count = count($array); //how many checkboxes returned
$i = 1;

foreach($array as $val)
{
    if(strlen($val) < 2)
        $val = '0'.$val;

    $col    = "a_b".$val;
    $alias  = "a_b".$val; //Because you're getting multiple of the same column (date) from the same table, this needs to be handled via joins with aliases.
    $select .= " EXTRACT(YEAR FROM ". $alias .".date) AS ". $alias ."_year, "; //This seems redundent, if you know the year why select it?
    $select .= $alias .".".$col." AS ".$alias;
    if($i < $count)
        $select .=",";

    $q      .= " JOIN (SELECT table2.id, table2.".$col.", table2.date FROM table2 WHERE EXTRACT(YEAR FROM table2.date) = '2000') AS ".$alias ." ON ".$alias.".id=table1.id";

    $i++;
}
$select .=" FROM table1";
$q = $select . $q;

但问题是,如果您还要更改位置“纽约”或年份。到目前为止,您将 ID 匹配上的日期和 a_b 值与纽约位置相关联。如果 a_b06 他们想要 2002 年的洛杉矶呢?

我强烈建议如下表结构:

locations
id      name        lng         lat
auto    NYC         X           Y
auto    LA          X           Y
auto    MIAMI       X           Y

values 
id      loc_id           date            key     value
auto    1 (NYC's auto)   2002-10-25      6       100
auto    1 (NYC's auto)   2001-10-25      5      150
auto    1 (NYC's auto)   2000-10-25      7      207

然后假设您的用户选择键 5、6、7 和 NYC,然后使用以下 PHP 来构建查询:

$array = array('5', '6', '7'); //Simulated checkbox return. In '' because they're strings not integers
$loc = "NYC";

$q =    'SELECT     EXTRACT(YEAR FROM `values`.date) as year,
                    `values`.key,
                    `values`.value,
                    locations.lat / CAST( 10 as FLOAT(6) ) as lat,
                    locations.lng / CAST( 10 as FLOAT(6) ) as lng
         FROM `values`
                JOIN locations ON locations.id = values.loc_id
         WHERE `values`.loc_id IN (SELECT locations.id FROM locations where locations.name = "'.$loc.'")
         AND values.key IN (';

$countVal = count($array);
$i = 1;
foreach($array as $value)
{
    $q .= $value;
    if($i < $countVal)
        $q .= ",";

    $i++;
}

$q .= ") 
ORDER BY `values`.date DESC";

哪个会返回:

year  key  value  lat                lng   
2002  6    100    4.070000076293946  -7.4  
2001  5    150    4.070000076293946  -7.4  
2000  7    207    4.070000076293946  -7.4   

我认为这更接近您正在寻找的内容。

【讨论】:

  • 感谢您的及时回复!我写了某种模式,希望它对你有某种意义。
  • 业务逻辑明智,table_2 中发生了什么。顺便说一句,如果您对每个可能的复选框都有一列,我可以告诉您您的数据会遇到问题。如果我知道业务逻辑,我可以建议对您的 SQL 结构进行调整,这将帮助您以更规范的方式检索您所追求的内容。除此之外,我会稍微看一下,看看我能做什么。 @vayacondios2015
  • 谢谢!我将等待您的回复。
  • 非常感谢您的详细解释!在 EXTRACT(YEAR FROM ". $alias .".date) AS ". $alias ."_year, "; 我没有提取年份,它应该保持原样: EXTRACT(YEAR FROM table2.date) AS year,这只是一个简单的尝试,看看复选框是否有效,稍后我会在我展开表单时通过简单的框输入选择年份。稍后我会更详细地查看您的回复,因为我现在无法连接到数据库。我可以看到有一些技巧对将来的编码很有用。我尝试了@Jujunol 给出的答案,好像
  • 不那么复杂,尽管它在某种程度上非常相似,正如我作为编程初学者所看到的那样。 你怎么看?而且我对数据库的优化(规范化)知之甚少,但感谢您指出这一点,尽管我没有更改它的设置的权限。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-25
  • 2019-07-27
  • 2013-09-05
  • 1970-01-01
  • 2014-10-25
  • 2016-01-22
  • 1970-01-01
相关资源
最近更新 更多