0

我有 2 个下拉菜单,用户可以使用下拉菜单过滤他们希望看到的学生和问题。可能的过滤器类型有:

  • 选择所有学生和所有问题
  • 选择所有学生和一个问题
  • 选择所有问题和一名学生
  • 选择一名学生和一个问题

下面是下拉菜单:

<p>
    <strong>Student:</strong>
    <select name="student" id="studentsDrop">
    <option value="All">All</option>
    <?php
    while ( $currentstudentstmt->fetch() ) {
    $stu = $dbStudentId;
    if(isset($_POST["student"]) && $stu == $_POST["student"]) 
        echo "<option selected='selected' value='$stu'>" . $dbStudentAlias . " - " . $dbStudentForename . " " . $dbStudentSurname . "</option>" . PHP_EOL;
    else
        echo "<option value='$stu'>" . $dbStudentAlias . " - " . $dbStudentForename . " " . $dbStudentSurname . "</option>" . PHP_EOL;
    }
    ?>
    </select>
    </p>

    <p>
    <strong>Question:</strong>
    <select name="question" id="questionsDrop">
    <option value="All">All</option>
    <?php
    while ( $questionsstmt->fetch() ) {
    $ques = $dbQuestionId;
    if(isset($_POST["question"]) && $ques == $_POST["question"]) 
        echo "<option selected='selected' value='$ques'>" . $dbQuestionNo . "</option>" . PHP_EOL;
    else
        echo "<option value='$ques'>" . $dbQuestionNo . "</option>" . PHP_EOL;
    }
    ?>
    </select>

</p>

现在我想设置一个 mysqli 查询来确定从下拉菜单中选择的学生和问题。

我的问题只是我需要设置 4 个查询来检查我从下拉菜单中提到的 4 种可能性,还是有更短的方法?

我必须使用:

 if ($_POST['question'] == 'All' && if ($_POST['student'] == 'All'){){

//NO WHERE CLAUSE

    if ($_POST['question'] == 'All' && if ($_POST['student'] != 'All'){){

//WHERE CLAUSE FOR FINDING SELECTED STUDENT

    if ($_POST['question'] != 'All' && if ($_POST['student'] == 'All'){){

//WHERE CLAUSE FOR FINDING SELECTED QUESTION 

    if ($_POST['question'] != 'All' && if ($_POST['student'] != 'All'){){

//WHERE CLAUSE FOR FINDING SELECTED QUESTION AND SELECTED STUDENT

更新:

我现在拥有的:

    function AssessmentIsSubbmitted()
{
    if(isset($_POST['answerSubmit'])) // we have subbmited the first form
    {

//QUERY 1: Student details depending on selected student(s)

if ($_POST['student'] == 'All'){

$selectedstudentqry = "
SELECT
StudentAlias, StudentForename, StudentSurname
FROM Student s
INNER JOIN Student_Session ss ON s.StudentId = ss.StudentId
WHERE SessionId = ?
ORDER BY StudentAlias
";

global $mysqli;
$selectedstudentstmt=$mysqli->prepare($selectedstudentqry);
// You only need to call bind_param once
$selectedstudentstmt->bind_param("i",$_POST["session"]);
// get result and assign variables (prefix with db)
$selectedstudentstmt->execute(); 
$selectedstudentstmt->bind_result($detailsStudentAlias,$detailsStudentForename,$detailsStudentSurname);
$selectedstudentstmt->store_result();
$selectedstudentnum = $selectedstudentstmt->num_rows();     

}else{  

$selectedstudentqry = "
SELECT
StudentAlias, StudentForename, StudentSurname
FROM
Student
WHERE
(StudentId = ?)
ORDER BY StudentAlias
";

global $mysqli;
$selectedstudentstmt=$mysqli->prepare($selectedstudentqry);
// You only need to call bind_param once
$selectedstudentstmt->bind_param("i",$_POST["student"]);
// get result and assign variables (prefix with db)
$selectedstudentstmt->execute(); 
$selectedstudentstmt->bind_result($detailsStudentAlias,$detailsStudentForename,$detailsStudentSurname);
$selectedstudentstmt->store_result();
$selectedstudentnum = $selectedstudentstmt->num_rows();    

}    


//QUERY 2: Question details depending on selected question(s)


if ($_POST['question'] == 'All'){

$selectedquestionqry = " SELECT q.QuestionNo, q.QuestionContent, o.OptionType, q.NoofAnswers, GROUP_CONCAT( DISTINCT Answer
                    ORDER BY Answer
                    SEPARATOR ',' ) AS Answer, r.ReplyType, q.QuestionMarks
                    FROM Question q
                    LEFT JOIN Answer an ON q.QuestionId = an.QuestionId
                    LEFT JOIN Reply r ON q.ReplyId = r.ReplyId
                    LEFT JOIN Option_Table o ON q.OptionId = o.OptionId
                    WHERE SessionId = ?
                    GROUP BY q.QuestionId
                    ORDER BY q.QuestionId";
";

global $mysqli;
$selectedquestionstmt=$mysqli->prepare($selectedquestionqry);
// You only need to call bind_param once
$selectedstudentstmt->bind_param("i",$_POST["session"]);
// get result and assign variables (prefix with db)
$selectedquestionstmt->execute(); 
$selectedquestionstmt->bind_result($detailsQuestionNo,$detailsQuestionContent,$detailsOptionType,$detailsNoofAnswers,
$detailsAnswer,$detailsReplyType,$detailsQuestionMarks);
$selectedquestionstmt->store_result();
$selectedquestionnum = $selectedquestionstmt->num_rows(); 


}else{

$selectedquestionqry = "
SELECT q.QuestionNo, q.QuestionContent, o.OptionType, q.NoofAnswers, GROUP_CONCAT( DISTINCT Answer
                    ORDER BY Answer
                    SEPARATOR ',' ) AS Answer, r.ReplyType, q.QuestionMarks
                    FROM Question q
                    LEFT JOIN Answer an ON q.QuestionId = an.QuestionId
                    LEFT JOIN Reply r ON q.ReplyId = r.ReplyId
                    LEFT JOIN Option_Table o ON q.OptionId = o.OptionId
                    WHERE QuestionId = ?
                    GROUP BY q.QuestionId
                    ORDER BY q.QuestionId
";

global $mysqli;
$selectedquestionstmt=$mysqli->prepare($selectedquestionqry);
// You only need to call bind_param once
$selectedquestionstmt->bind_param("i",$_POST["question"]);
// get result and assign variables (prefix with db)
$selectedquestionstmt->execute(); 
$selectedquestionstmt->bind_result($detailsQuestionNo,$detailsQuestionContent,$detailsOptionType,$detailsNoofAnswers,
$detailsAnswer,$detailsReplyType,$detailsQuestionMarks);
$selectedquestionstmt->store_result();
$selectedquestionnum = $selectedquestionstmt->num_rows(); 

}

//QUERY 3: Student Answers depending on selected student(s) and selected question(s)

$studentanswerqry = "
SELECT
sa.StudentId, sa.QuestionId, GROUP_CONCAT(DISTINCT StudentAnswer ORDER BY StudentAnswer SEPARATOR ',') AS StudentAnswer, ResponseTime, MouseClick, StudentMark
FROM Student_Answer sa
INNER JOIN Student_Response sr ON sa.StudentId = sr.StudentId
WHERE
(sa.StudentId = ? AND sa.QuestionId = ?)
GROUP BY sa.StudentId, sa.QuestionId
";

global $mysqli;
$studentanswerstmt=$mysqli->prepare($studentanswerqry);
// You only need to call bind_param once
$studentanswerstmt->bind_param("ii",$_POST["student"], $_POST["question"]);
// get result and assign variables (prefix with db)
$studentanswerstmt->execute(); 
$studentanswerstmt->bind_result($detailsStudentAnswer,$detailsResponseTime,$detailsMouseClick,$detailsStudentMark);
$studentanswerstmt->store_result();
$studentanswernum = $studentanswerstmt->num_rows(); 


}

?>
4

3 回答 3

3

您可以迭代地构建一个WHERE子句。考虑一个WHERE子句进行显式过滤,因此对于您选择“全部”某物的情况,您不需要添加任何过滤器。其他过滤器是相互建立的,所以我们可以简单地将它们与ANDs连接起来WHERE

$query = 'SELECT ... FROM ...';

// Initially empty
$where = array();
$parameters = array();

// Check whether a specific student was selected
if($stu !== 'All') {
    $where[] = 'stu = ?';
    $parameters[] = $stu;
}

// Check whether a specific question was selected
// NB: This is not an else if!
if($ques !== 'All') {
    $where[] = 'ques = ?';
    $parameters[] = $ques;
}

// If we added to $where in any of the conditionals, we need a WHERE clause in
// our query
if(!empty($where)) {
    $query .= ' WHERE ' . implode(' AND ', $where);
}

$result = prepare_and_execute_query($query, $parameters);

好的,所以查看您的更新,您有一组相当复杂的查询,但可以将其组合成一个语句。试试这个:

SELECT
    s.StudentId, s.StudentAlias, s.StudentForename,         -- Student fields
    s.StudentSurname,
    q.QuestionId, q.QuestionNo, q.QuestionContent,          -- Question fields
    q.OptionType, q.NoofAnswers, q.Answer, q.ReplyType,
    q.QuestionMarks,
    GROUP_CONCAT(DISTINCT sa.StudentAnswer ORDER BY         -- Answer fields
        sa.StudentAnswer SEPARATOR ',') AS StudentAnswer,
    sr.ResponseTime, sr.MouseClick, sr.StudentMark
FROM Student s
INNER JOIN Student_Answer sa ON (s.StudentId = sa.StudentId)
INNER JOIN Question q ON (sa.QuestionId = q.QuestionId)
INNER JOIN Student_Response sr ON (sa.StudentId = sr.StudentId)
WHERE                     -- This WHERE clause may be entirely removed, 
                          -- depending on the filters
    s.StudentId = ? AND   -- This is removed if $_POST['student'] is 'All'
    q.QuestionId = ?      -- This is removed if $_POST['question'] is 'All'
GROUP BY sa.StudentId, q.QuestionId

我认为这会做你想要的。我不太确定哪些字段是其中的一部分,Student_Response哪些是其中的一部分,Student_Answer因此您可能不得不摆弄SELECT.


不幸的是,这种方法不适用于您的用例。但是我们仍然可以考虑我提出的原始逻辑如何与您给出的一个查询一起工作:

$selectedstudentqry = "
SELECT
StudentAlias, StudentForename, StudentSurname
FROM
Student ";
if($_POST['student'] !== 'All') { // Check here
    $selectedstudentqry .= "
    WHERE
    (StudentId = ?) ";
}
$selectedstudentqry .= "
ORDER BY StudentAlias
";

global $mysqli;
$selectedstudentstmt=$mysqli->prepare($selectedstudentqry);
if($_POST['student'] !== 'All') {
    // You only need to call bind_param once
    $selectedstudentstmt->bind_param("i",$_POST["student"]);
}
// get result and assign variables (prefix with db)
$selectedstudentstmt->execute(); 
$selectedstudentstmt->bind_result($detailsStudentAlias,$detailsStudentForename,$detailsStudentSurname);
$selectedstudentstmt->store_result();
$selectedstudentnum = $selectedstudentstmt->num_rows();

请注意我们如何简单地将外部ifs 移动到代码中更具体的位置以减少代码重复。如果你看到像你一样的重复,很有可能你正在做一些事情,比如让你的条件句过于宽泛。不过,您肯定在尝试简化这一点并减少冗余方面走在正确的轨道上。

于 2013-01-26T03:06:41.793 回答
0

这是我在有 64 种用户输入排列时使用的代码。可以有来自另一个页面的乘客 ID、部分名字和/或姓氏、年份、月份或课程 ID。

用各种 AND、IS LIKE 等构建 where 子句的一部分。

$params = array();
$types = "";


if ( isset($_GET["riderid"]) && $_GET["riderid"] )  {
    $where = sprintf (' AND %s.id = ?', $tables["rider"]);
    $params[]= $_GET["riderid"];
    $types = $types .'i';

} else {
    if ( isset($_GET["last"]) && $_GET["last"] ) {

        $where = sprintf(' AND %s.last like ?', $tables["rider"]);
        $params[] = $_GET["last"] . "%";
        $types = $types . "s";
    }

    if ( isset($_GET["first"]) && $_GET["first"] ) {

        $whereFirst = sprintf(' AND %s.first like ?', $tables["rider"]);
        $where = $where . $whereFirst;
        $params[] = $_GET["first"] . "%";
        $types = $types . "s";
    }
}

if ( isset($_GET["year"]) && $_GET["year"] && $_GET["year"] != -1 )  {
    $whereYear = sprintf(' AND YEAR(%s.date) = ?', $tables["race"]);
    $where = $where . $whereYear;
    $params[] = $_GET["year"];
    $types = $types . "i";
}

if ( isset($_GET["month"]) && $_GET["month"] && $_GET["month"] != -1 )  {
    $whereMonth = sprintf(' AND month(%s.date) = ?', $tables["race"]);
    $where = $where . $whereMonth;
    $params[] = $_GET["month"];
    $types = $types . "i";

}  

if ( isset($_GET["courseid"]) && $_GET["courseid"] && $_GET["courseid"] != -1 ) {
    $whereCourse = sprintf(' AND %s.courseid = ?', $tables["race"]);
    $where = $where . $whereCourse;
    $params[] = $_GET["courseid"];
    $types = $types . "i";
}

这是查询。

    //
    // Show selected races
    //
    $listQuery = "SELECT {$tables["race"]}.raceid, {$tables["race"]}.typeid, " .
             "           tag,  {$tables["race"]}.date, " .
             "           {$tables["location"]}.name, {$tables["course"]}.dist, " .
             "           {$tables["course"]}.description,  " .
             "           {$tables["result"]}.time, {$tables["result"]}.dnf, " .
             "           {$tables["rider"]}.first, {$tables["rider"]}.last ".
             "  FROM {$tables["race"]}, {$tables["sysracetype"]}, " .
             "       {$tables["course"]}, {$tables["location"]}, " .
             "       {$tables["result"]}, {$tables["rider"]} " .
             " WHERE {$tables["race"]}.courseid = {$tables["course"]}.courseid " .
             "   AND {$tables["race"]}.typeid = {$tables["sysracetype"]}.typeid " .
             "   AND {$tables["course"]}.locid = {$tables["location"]}.locid " .
             "   AND {$tables["race"]}.raceid = {$tables["result"]}.raceid" .
             "   AND {$tables["result"]}.riderid = {$tables["rider"]}.id" .
             $where .
             $orderby;

准备和绑定参数。

$stmt = mysqli_prepare ($db_connection, $listQuery);
// 
// Handle the varying number of SQL parameters / place holders.
// Push the first two parameter of mysqli_stmt_bind_param
//
$bindArgs = array ($stmt, $types);

//
// Change parameters to refs  (depends on PHP version)   
//
foreach ($params as $key => $value)  
    $bindArgs[] =& $params[$key];

//
// Use "call back" to pass all params.
//
call_user_func_array("mysqli_stmt_bind_param", $bindArgs);
于 2016-03-07T15:44:44.903 回答
-1

我以这种方式解决了类似的问题。其中 $parmMap 是用 2 (1,2) 的幂构造的,因为我检测到每个可选的 WHERE 子句项并附加适当的 AND fieldName = ?。

switch ($parmMap ) {
    case 0:
      break;
    case 1:
      mysqli_stmt_bind_param ($stmt, "i", $courseParm );
      break;
    case 2:
      mysqli_stmt_bind_param ($stmt, "i", $yearParm );
      break;
    case 3:
      mysqli_stmt_bind_param ($stmt, "ii", $courseParm, $yearParm );
      break;
    default:
      break;
}

我不会将它用于另一个有六个可选 where 子句条件的查询!我发现了call_user_func_array

于 2016-03-05T19:21:58.070 回答