首页 > 解决方案 > 我应该使用哪个 SQL 请求?

问题描述

我有桌子SkillsResult

___ Matieres ___             ___ Resultats ___
id (int auto increment)      ID (int auto_increment)
Nom (varchar)            TIME_OF_INSERTION (datetime current_timestamp)
Categorie (varchar)          ID_USER (int)
Active (boolean)             ID_MATIERE (int)
                             RESULTAT (int)

我有这段代码可以根据查询的数据创建一个表单:

$req = $bdd->query(SELECT * FROM Matieres LEFT JOIN Resultats ON Matieres.id = Resultats.ID_MATIERE WHERE Active = TRUE);

$skills = [];

while( $data = $req->fetch()) {

    array_push( $skills, [ $data['id'], $data['Nom'], $data['RESULTAT'] ] );

}

function setWidgetValue( $skill ) {
    
    if(is_null($skill[2])) {
        $value = 0;
    } else {
        $value = $skill[2];
    }

    $widget = "<div class='m-5'><p>".$skill[1]."</p><input type='range'  value='" . $value ."' class='form-control-range' min='0' step='1' max='10' id='".$skill[0]."' name='valSkill' onchange=\"MAJ_Value( ".$skill[0].", this.value, " . $_SESSION['id'] . " )\" ></div>";
    return $widget;

}


function setAllWidgetValue( $skills  ) {

    $widget = "<div id='valSkills' >\n";
    foreach( $skills as $skill )
        $widget .= setWidgetValue( $skill );
    $widget .= "</div>";
    return $widget;

}

问题是我的输入值应该是0如果用户还没有发送它们并且如果一个用户发送它就可以正常工作。但是,如果另一个用户尝试访问表单,则输入将具有前一个用户提交的值。

我认为问题出在 SQL 请求中,但我找不到一个完美运行的 :( 我知道我必须传递id用户的,但不知道在请求中写在哪里

标签: phpsqldatabasejoinselect

解决方案


一点关于 SQL 的知识

你的表和你的表之间好像有one-many关系?MatieresResultat

SELECT...JOIN在这种情况下使用语句时,您有效Matieres地返回Resultat.

例如:

  1. 假设你有一个技能/matierecan touch toes
  2. 假设有谁拥有该技能的5记录Resultatusers

使用您当前的查询结构,您可以执行以下操作:

__SQL:

SELECT Resultat.ID_USER, Matieres.Nom, Result.RESULTAT
FROM Matieres
    LEFT JOIN Resultat ON Matieres.id = Result.ID_SKILL


__RESULTS:

Resultat.ID_USER     Matieres.Nom        Resultat.RESULTAT
1                    can touch toes      50
2                    can touch toes      71
3                    can touch toes      23
4                    can touch toes      88
5                    can touch toes      20

要更改此行为,您需要在ON子句中指定附加条件:

__SQL:

SELECT Resultat.ID_USER, Matieres.Nom, Result.RESULTAT
FROM Matieres
    LEFT JOIN Resultat
        ON Matieres.id = Result.ID_SKILL
            AND Resultat.ID_USER = 1

__RESULTS:

Resultat.ID_USER     Matieres.Nom        Resultat.RESULTAT
1                    can touch toes      50

PHP while 语句回显重复:在此处查看答案以获取更多信息和示例

ON 不是 WHERE

附加条件必须进入ON子句而不是WHERE子句的原因是你想要获得每一项Active技能/matiere,无论是否有人已经获得了Resultat它。

如果我们将它放入WHERE子句中,我们会得到:

__SQL: 

SELECT Resultat.ID_USER, Matieres.Nom, Result.RESULTAT
FROM Matieres
    LEFT JOIN Resultat
        ON Matieres.id = Result.ID_SKILL
WHERE Resultat.ID_USER = 1

__RESULTS:

Resultat.ID_USER     Matieres.Nom        Resultat.RESULTAT
1                    can touch toes      50

除非您考虑到您拥有多种技能/材料并且用户没有每个技能/材料的记录,否则这似乎还可以......例如:

__TABLES

Matieres                         Resultat
id           Nom                 ID_USER     ID_MATIERE      RESULTAT
111          can touch toes      1           111             54
112          can handstand       1           112             60
113          can cartwheel       2           113             72

.

__SQL[1]: {For ID_USER == 1; using ON}

SELECT Resultat.ID_USER, Matieres.Nom, Result.RESULTAT
FROM Matieres
    LEFT JOIN Resultat
        ON Matieres.id = Result.ID_SKILL
            AND Resultat.ID_USER = 1

__RESULT[1]: 

Matieres                         Resultat
id           Nom                 ID_USER     ID_MATIERE      RESULTAT
111          can touch toes      1           111             54
112          can handstand       1           112             60
113          can cartwheel       NULL        NULL            NULL


__SQL[2]: {For ID_USER == 2; using ON}

SELECT Resultat.ID_USER, Matieres.Nom, Result.RESULTAT
FROM Matieres
    LEFT JOIN Resultat
        ON Matieres.id = Result.ID_SKILL
            AND Resultat.ID_USER = 2

__RESULT [2]:

Matieres                         Resultat
id           Nom                 ID_USER     ID_MATIERE      RESULTAT
111          can touch toes      NULL        NULL            NULL
112          can handstand       NULL        NULL            NULL
113          can cartwheel       2           113             72


__SQL[3]: {For ID_USER == 1; using WHERE}

SELECT Resultat.ID_USER, Matieres.Nom, Result.RESULTAT
FROM Matieres
    LEFT JOIN Resultat
        ON Matieres.id = Result.ID_SKILL
WHERE Resultat.ID_USER = 1

__RESULT[3]: 

Matieres                         Resultat
id           Nom                 ID_USER     ID_MATIERE      RESULTAT
111          can touch toes      1           111             54
112          can handstand       1           112             60


__SQL[4]: {For ID_USER == 2; using WHERE}

SELECT Resultat.ID_USER, Matieres.Nom, Result.RESULTAT
FROM Matieres
    LEFT JOIN Resultat
        ON Matieres.id = Result.ID_SKILL
WHERE Resultat.ID_USER = 2

__RESULT[4]: 

Matieres                         Resultat
id           Nom                 ID_USER     ID_MATIERE      RESULTAT
113          can cartwheel       2           113             72

你的问题

假设

  1. 您已user登录到该网站$_SESSION["id"] == Resultat.ID_USER
  2. 你想要SELECT所有已经Matieres.id && Matieres.Nom 记录 Resultat.RESULTAT的技能Resultat.ID_USER
  3. 您正在使用PDO并且$bdd是您与数据库的连接

示例代码

// SQL statement using `?` as a placeholder for the users id (from $_SESSION["id"]
// Add: "AND Resultats.ID_USER = ?" to ON clause to limit joined records to currently logged in user
$sql = "    
    SELECT Matieres.id, Matieres.nom, Resultats.RESULTAT
    FROM Skills
        LEFT JOIN Resultats ON Matieres.id = Resultats.ID_MATIERE AND Resultats.ID_USER = ?
    WHERE Matieres.Active = TRUE
";

$req = $bdd->prepare($sql);         // Prepare query
$req->execute([ $_SESSION["id"] ]); // Assign value to place holder and execute query

$skills = [];
while( $data = $req->fetch() ) {
    $skills[] = [
        "id"=>$data["id"],
        "Nom"=>$data["Nom"],
        "RESULTAT"=>$data["RESULTAT"]
    ];
}

function setWidgetValue( $skill ) {

    // Set values outside of "widget" string for ease of reading
    $value    = ( is_null($skill["RESULTAT"]) ) ? 0 : $skill["RESULTAT"]; // Shorthand if statement using the ternary operator
    $nom      = $skill["Nom"];   
    $skill_id = $skill["id"];  
    $user_id  = $_SESSION["id"];

    // I've separated the code over several lines to make 
    // it easier to read you can of course change it back!
    $widget   = "
        <div class='m-5'>
            <p>{$nom}</p>
            <input
                type='range' 
                value='{$value}'
                class='form-control-range'
                min='0' step='1' max='10'
                id='{$skill_id}'
                name='valSkill'
                onchange=\"MAJ_Value( {$skill_id}, this.value, {$user_id} 
                )\" >
        </div>
    ";
    return $widget;
}

function setAllWidgetValue( $skills ) {
    $widget = "<div id='valSkills' >\n";
    foreach( $skills as $skill )
        $widget .= setWidgetValue( $skill );
    $widget .= "</div>";
    return $widget;
}

推荐阅读