【问题标题】:PHP select multiple Array tablesPHP选择多个数组表
【发布时间】:2016-07-09 18:04:01
【问题描述】:

是否可以SELECT 使用多个数组表。我知道这听起来令人困惑,但这是我所做的:

首先,我创建了一个表单,它有两个复选框选项,如下所示:

<form action="something.php" method="post">
<input type="checkbox" name="store[]" value="M1">
<input type="checkbox" name="store[]" value="M2">
<input type="submit" value="Go">
</form>

现在提交表单后,我可以通过foreach loop查看选择的商店:

$allstore = $_POST['store'];
 foreach ($allstore as $store=>$value) {
echo $value;
}

到目前为止,一切都按需要工作! 然而,复选框中的这两个值被认为是 表名 !现在我怎样才能找到一种方法让 PHP 根据用户选择 $value 选择一个或两个表?

$query = "SELECT * from **{$allstore[0]},{$allstore[1]}** WHERE .....";

如您所见,{$allstore[0]},{$allstore[1]} 应该基于 foreach 循环创建。我似乎无法找到这样做的方法!我可以插入一个函数来为我做这件事吗?

像这样:$query = "SELECT * from ((( Function Here ))) WHERE .....";

如果你有不同的做法,请分享。


编辑:

M1 表

id |item_no |qty |price
1   x1       10   20
2   x2       5    22
3   x3       3    5

M2 表

id |item_no |qty |price
1   x1      11    20
2   x9      5     30
3   x10     6     26

输出表应该是

item_no | price |   M1 |  M2
x1         20       10    11
x2         22       5     N/A
x3         5        3     N/A
x9         30       N/A   5
x10        26       N/A   6

这就是我的目标。希望能解决!

【问题讨论】:

  • 如果用户没有选择所有的表,输出应该是什么?如果两个表中的价格不同,price 列中的内容是什么?你想要的看起来像FULL OUTER JOIN,这是 MySQL 没有的;请参阅stackoverflow.com/questions/4796872/full-outer-join-in-mysql 了解解决方法。
  • 好吧,我可以保证无论如何价格都是固定的。其次,除非选中 1 个复选框,否则用户无法提交表单。
  • 我的意思是,如果他们只选择一张桌子,而不是两者都选择,结果应该是什么。如果他们只选择 M1,那么 M2 列中的内容是什么?
  • 如果所有表中的价格都相同,这是不好的标准化,应该有另一个表包含项目的价格。
  • 可以有2张以上的桌子吗?您是否需要一个适用于任意数量表或仅 2 个表的解决方案?

标签: php mysql arrays select


【解决方案1】:

这是 2 个表的结构 sqlfiddle 我认为您可以从这里添加更多表格。

SELECT T1.item_no,
  COALESCE(M1.price,M2.price) as price,
  M1.qty as M1,
  M2.qty as M2
FROM
  (SELECT item_no FROM M1
    UNION
   SELECT item_no FROM M2
   )T1
   LEFT JOIN M1 ON T1.item_no = M1.item_no
   LEFT JOIN M2 ON T1.item_no = M2.item_no

更新:我对 PHP 不太熟悉,但我查阅了一些语法,并且能够基于 ["M1","M2"] 或 ["M1"] 或 ["M2" 的数组动态生成 SQL ]

DynamicPHPtobuildSQL

<?php
        //Enter your code here, enjoy!

$allstore = ["M2"];
$item = 0;
$sqlpart1 = "";
$sqlpart2 = "";
$sqlpart3 = "";
$sqlpart4 = "";
foreach ($allstore as $store=>$value) {
   $item += 1;
   if ($item > 1){
     $sqlpart1 .= ",";
     $sqlpart2 .= ",";
     $sqlpart3 .= " UNION ";
   }
   $sqlpart1 .= $value . ".price ";
   $sqlpart2 .= $value . ".qty as " . $value . " ";
   $sqlpart3 .= "SELECT item_no FROM " . $value . " ";
   $sqlpart4 .= "LEFT JOIN " . $value . " ON T1.item_no=" . $value . ".item_no ";
}
$SQL = "SELECT T1.item_no,COALESCE(" . $sqlpart1 . ") as price," . $sqlpart2;
$SQL .= "FROM (" . $sqlpart3 . ")T1 " . $sqlpart4;
echo $SQL;
?>

【讨论】:

  • 感谢您的回答,但如果我知道如何让用户选择他想查看的表格,这将非常方便。我的意思是你已经分配了 M1 和 M2 却没有注意到它需要从 checkbox 中选中。其中可能只有 M1,或仅 M2 ..或两者。我完全失去了找到合适解决方案的希望。
  • 您可以根据我认为在 PHP 中选择的 SQL 动态构建 SQL。就像 M1.price,M2.price 可以构建... M1.qty as M1,M2 .qty as M2 can be build up... SELECT item_no FROM M1 UNION SELECT item_no FROM M2 can be build up... 与 LEFT JOIN M1 ON T1.item_no = M1.item_no LEFT JOIN M2 ON T1.item_no 相同建立....根据用户选择的内容,您可以构建每个部分并将这些部分连接在一起以构建您的最终查询
  • 我已经用 PHP 代码更新了我的答案,让您了解如何动态生成 SQL 希望对您有所帮助
【解决方案2】:

小心避免SQL injection 的风险:将发布的值与现有存储表名称的封闭列表进行比较,并拒绝任何其他值。

还要注意,不仅FROM 子句受用户选择的影响,SELECT 子句也受到影响。因此,您的 SQL 语句中有两个动态部分。

您可以使用这段代码,它利用了array_intersectimplodearray_map

$selected_stores = $_POST['store'];

// Protect against SQL-injection by only accepting known tables:
$all_stores = array("M1", "M2", "M3");
$selected_stores = array_intersect($selected_stores, $all_stores);

// Build dynamic part of the FROM clause
$from = implode("
           UNION
           ", array_map(function ($store) { 
    return "SELECT '$store' as store, item_no, price, qty FROM $store";
}, $selected_stores));

// Build dynamic part of the SELECT clause
$cols = implode(",
     ", array_map(function ($store) { 
    return "CASE store WHEN '$store' THEN qty END AS $store";
}, $selected_stores));

$sql = "
SELECT   item_no,
         MAX(price) as price,
         $cols
FROM     ( $from ) data
GROUP BY item_no
";

生成的 SQL 如下所示:

SELECT   item_no,
         MAX(price) as price,
         CASE store WHEN 'M1' THEN qty END AS M1,
         CASE store WHEN 'M2' THEN qty END AS M2
FROM     ( SELECT 'M1' as store, item_no, price, qty FROM M1
           UNION
           SELECT 'M2' as store, item_no, price, qty FROM M2 ) data
GROUP BY item_no

另见this SQL fiddle

作为旁注:我建议将所有商店表合并到一个表中,该表将有一个额外的列指示商店。这更符合规范化的数据库设计,并且在搜索、排序、性能和简单性方面的优势多于劣势。

【讨论】:

    猜你喜欢
    • 2017-11-11
    • 1970-01-01
    • 2011-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多