1

私の質問には、SQL を使用して、スクリプトを使用して、重複した値の複数のグループにグループ ID を割り当てることが含まれます。私は少しの間手作業でそれを行ってきましたが、データベースの広がり (数千の要素) では、時間がかかることに気付きました。

これが私のDB構造です:

id  | db quesition         | db keywords           | answer id  | db answer                    |
------------------------------------------------------------------------------------------------
 0  | Why is Mars red?     | [why,mars,red]        | 0          | Mars is red because blah     |

 1  | How is Mars red?     | [how,mars,red]        | 0          | Mars is red because blah     |

 2  | What makes Mars red? | [what,makes,mars,red] | 0          | Mars is red because blah     |

 3  | Is Mars very rocky?  | [is,mars,rocky]       | 0          | Yes Mars is rocky blahbla    |

 4  | Does Mars have rocks?| [mars,have,rocks]     | 0          | Yes Mars is rocky blahbla    |

 5  | What is the Sun?     | [what,is,sun]         | 0          | The Sun is our solar blah    |

 6  | What is a star?      | [what,is,star]        | 0          | A star is a ball of hot blah |

ご覧のとおり、1 つの回答に対して複数の質問が存在する可能性があるため、データベースのdb_answer列には重複があります。答えが複数回使用された場合に繰り返されるdb_answer単数形をそれぞれに持たせたいと思います。answer_id説明するために、db を次のようにしたいと思います。

id  | db quesition         |  db keywords          | answer id | db answer                    |
-----------------------------------------------------------------------------------------------
 0  | Why is Mars red?     | [why,mars,red]        | 1         | Mars is red because blah     |

 1  | How is Mars red?     | [how,mars,red]        | 1         | Mars is red because blah     |

 2  | What makes Mars red? | [what,makes,mars,red] | 1         | Mars is red because blah     |

 3  | Is Mars very rocky?  | [is,mars,rocky]       | 2         | Yes Mars is rocky blahbla    |

 4  | Does Mars have rocks?| [mars,have,rocks]     | 2         | Yes Mars is rocky blahbla    |

 5  | What is the Sun?     | [what,is,sun]         | 3         | The Sun is our solar blah    |

 6  | What is a star?      | [what,is,star]        | 4         | A star is a ball of hot blah |

これを行うスクリプトを広範囲に探しましたが、運がありませんでした。私がやろうとしていることを示すためのメモとして、IDを追加したい回答グループごとにSQLを使用しています。

UPDATE elements SET answer_id = '1' WHERE db_answer = 'Mars is red because blah' 
4

3 に答える 3

3

これは、PHPスクリプトを使用すると非常に簡単になります。

$query = mysql_query("SELECT DISTINCT db_answer FROM elements");
$i = 1;
while ($row = mysql_fetch_row($query))
{
    mysql_query("UPDATE elements SET answer_id = {$i} WHERE db_answer = '{$row[0]}'");
    $i++;
}

answer_idただし、回答を別のテーブルに保存し、テーブルに保持するのが賢明だと思いelementsます。そうすれば、情報が不必要に重複するのを防ぐことができます。


編集 :

@mdoyleが提案したように、4つのテーブルを使用するのが最善だと思います。

CREATE TABLE questions (
    questionID INT NOT NULL AUTO_INCREMENT,
    question VARCHAR(128),
    answerID INT,
    PRIMARY KEY (questionID),
    FOREIGN KEY (answerID) REFERENCES answers (answerID)
);

CREATE TABLE answers (
    answerID INT NOT NULL AUTO_INCREMENT,
    answer VARCHAR(128),
    PRIMARY KEY (answerID)
);

CREATE TABLE keywords (
    keywordID INT NOT NULL AUTO_INCREMENT,
    keyword VARCHAR(16),
    PRIMARY KEY (keywordID)
);

CREATE TABLE question_keywords (
    questionID INT,
    keywordID INT,
    FOREIGN KEY (questionID) REFERENCES questions (questionID),
    FOREIGN KEY (keywordID) REFERENCES keywords (keywordID)
);

answersテーブルとテーブルの関係questions1対多1つの回答が多くの質問に当てはまる場合があります)であるため、2つのテーブルがあります。これは、各質問が1つだけの回答を持つことができることを前提としています。そうではなく、1つの質問に2つの受け入れ可能な答えがある可能性がある場合、関係は多対多になります(多対多の関係のテーブルを設定する方法については読み続けてください)。

questionsテーブルとテーブルの関係keywords多対多であるため(多くの質問で多くのキーワードが使用される場合があります)、3つのテーブルがあります。1つは質問を保持し(質問ごとに1行)、1つはキーワードを保持し(キーワードごとに1行)、3つ目は2つを結び付けます。テーブルには、同じquestionIDを持つ複数のquestion_keywords行と、同じkeywordIDを持つ複数の行があります。したがって、questionID 5に3つのキーワードがある場合question_keywords、questionIDが5のテーブルに3つのエントリがあります。

1対1の関係の場合、通常、同じテーブルに追加の列を作成するだけで安全なので、その関係に対して1つのテーブルがあります。

注:VARCHAR列の長さは自由に変更してください。あなたの例に基づいて、大丈夫かもしれない値を選びましたが、質問や回答がもっと長くなる可能性がある場合は、このサイズを増やす必要があるかもしれません。


これらのテーブルを作成したら、次のようにしてテーブルにデータを入力できます。

$query = $mysql_query("SELECT * FROM elements") or die(mysql_error());
echo "About to enter while-loop<br />";
$i = 1;
while ($row = mysql_fetch_assoc($query))
{
    echo "loop ". $i++ ."<br />";
    $answerID = -1;

    $querystr = "SELECT answerID FROM answers WHERE answer = '{$row["db_answer"]}'";
    echo "Getting answerID. query: {$querystr}<br />";
    $query = mysql_query($querystr) or die($mysql_error());
    if (!(list($answerID) = mysql_fetch_row($query)))
    {
        $querystr = "INSERT INTO answers (answer) VALUES ('{$row["db_answer"]}')";
        echo "Answer did not exist, inserting now. query: {$querystr}<br />";
        mysql_query($querystr) or die(mysql_error());
        $answerID = mysql_insert_id();
    }

    $querystr = "INSERT INTO questions (questionID, question, answerID) VALUES ('{$row["id"]}', '{$row["db_question"]}', '{$answerID}')";
    echo "Inserting question. query: {$querystr}<br />";
    mysql_query($querystr) or die(mysql_error());

    $keywords = explode(",", trim($row["db_keywords"], "[]"));
    echo "keywords = ". print_r($keywords, true) ."<br />";
    foreach ($keywords as $keyword)
    {
        $keywordID = -1;
        $querystr = "SELECT keywordID FROM keywords WHERE keyword = '{$keyword}'";
        echo "Getting keywordID. query: {$querystr}<br />";
        $query = mysql_query($querystr) or die(mysql_error());
        if (!(list($keywordID) = mysql_fetch_row($query)))
        {
            $querystr = "INSERT INTO keywords (keyword) VALUES ('{$keyword}')";
            echo "Keyword did not exist, inserting now. query: {$querystr}<br />";
            mysql_query($querystr) or die(mysql_error());
            $keywordID = mysql_insert_id();
        }

        $querystr = "INSERT INTO question_keywords (questionID, keywordID) VALUES ('{$row["id"]}', '{$keywordID}')";
        echo "Inserting question keyword. query: {$querystr}<br />";
        mysql_query($querystr) or die(mysql_error());
    }
}

これを実行し、4つのテーブルが正しく入力されていることを確認すると、テーブルを使用する必要がなくなりますelements。これらの4つのテーブル(、、、、および)を使用questionsするだけanswersです。keywordsquestion_keywords

于 2012-04-18T19:54:03.103 に答える
2

mysql の制限内で、次のように回答に ID を割り当てることができます。

select answer, min(id) as answer_id
from table
group by answer

したがって、完全な解決策は、テーブルに answerid 列を作成してから、次のようにすることです。

with aid as 
(
  select answer, min(id) as answer_id
  from table
  group by answer
)
update table
set answer_id = aid.answer_id
where table.answer = aid.answer
于 2012-04-18T20:33:48.203 に答える
1

クエリでこれを行うために必要なのは、SQL Server関数ROW_NUMBER()です。残念ながら、MySQLにはこれがありません。ただし、変数のインライン割り当てを利用して関数をエミュレートできます。関連するロジックを説明する記事は次のとおりです。http://www.explodybits.com/2011/11/mysql-row-number/

于 2012-04-18T20:00:33.257 に答える