我正在使用MYSQL.My表包含列名为Revenue2000,Revenue2001,Revenue2002,....,Revenue 2016,Revenue 2017
传统方式(手动选择所有列):
select Revenue2005,
Revenue2006,
Revenue2007,
Revenue2008,
Revenue2009,
Revenue2010
from table_name
期望的方式:
我想写一个动态选择语句。应该有2个变量“start”和“end”,这样我就可以使它成为动态的。用户可以选择指定起始年份和结束年份,并可以查看所需的结果。
在上述情况下,Start year = 2005 结束年份= 2010
答案 0 :(得分:0)
是的,这是一个糟糕的数据库设计,最好的答案是“根本不做这件事,只需修理你的桌子。”#34;不幸的是,有时你会被其他人制造的东西困住,并且无论出于什么原因都无法改变它,但你仍需要完成某些事情(欢迎来到我的生活中)。我会这样做:
从用户输入获取多年并将其转换为整数,以防有人输入愚蠢/顽皮的东西。不要依赖客户端验证。准备好的陈述在这里不会对您有所帮助,因为它们将用作列名的一部分。
$start = (int) $_POST['start'];
$end = (int) $_POST['end'];
进行快速健全性检查以确保范围有意义并且应该与数据库中的内容一起使用。
if ($start > $end
|| $start < $lowest_year_in_your_db
|| $end > $highest_year_in_your_db) {
// quit with error
}
然后,您可以生成要在查询中使用的列的列表。这是range
和array_map
的一种方式,但您也可以使用for循环构建一个字符串。
$columns = implode(', ', array_map(function($year) {
return "Revenue$year";
}, range($start, $end)));
$sql = "SELECT $columns FROM table_name";
理论上,应该能够实现的最糟糕的事情是,您获得的列不存在,并且您的查询将失败。
但实际上,如果你有任何选择,不要这样做。按照人们在评论中说明的那样规范化您的数据库,或者找到谁继续向数据库添加更多年份列并让他们这样做。
答案 1 :(得分:0)
正如已经指出的那样,数据库设计太可怕了。你应该把它标准化,这是值得的。
但是,如果目前无法做到这一点,则以下代码应该完全符合您的要求:
// Connect to DB
$mysqli = new mysqli("localhost", "USERNAME", "PASSWORD", "DATABASE");
// Get column names
$columns = $mysqli->query('SHOW COLUMNS FROM revenue')->fetch_all();
$columnNames = array_column($columns, 0);
// Extract years from column names
$years = array_map(function($columnName) {
return (int) substr($columnName, -4);
}, $columnNames);
// Get max and min year
$maxYear = max($years);
$minYear = min($years);
// Input year start and end
$start = (int) $_POST['start']; // User-input
$end = (int) $_POST['end']; // User-input
// Avoid wrong inputs
if($start > $end || $start < $minYear || $end > $maxYear) {
die('Error');
}
// Create the SQL-query
$selectColumns = [];
for ($i = $start; $i <= $end; $i++) {
$selectColumns[] = "revenue" . $i;
}
$queryString = "SELECT " . implode(", ", $selectColumns) . " FROM TABLE";
// Run the query
// ...