在筛选结果时,是否有更短的方法来设置查询?

时间:2013-01-26 02:55:35

标签: php mysqli

我有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(); 


}

?>

3 个答案:

答案 0 :(得分:3)

您可以迭代地构建WHERE子句。考虑WHERE子句进行显式过滤,因此对于您选择“全部”某些内容的情况,您不需要添加任何过滤器。其他过滤器相互构建,因此我们只需将其与AND中的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();

请注意我们如何简单地将外部if移动到代码中更具体的位置以减少代码重复。如果你看到像你一样的重复,那么你很有可能会做出像你的条件太宽泛一样的事情。尽管如此,你肯定在努力简化这一过程并减少冗余。

答案 1 :(得分: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);

答案 2 :(得分:-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