2

ステップバイステップまたは手続き型アプリケーションにやや似たWebアプリケーションを考え出そうとしています。私はそれを実際に説明することはできず、それを呼び出す方法もわかりませんが、それは、求人応募などの特定のものを達成する方法について段階的な指示を提示するアプリケーションです.

「ユーザーが物事を行う方法を支援するアプリケーション。」

そこで、いくつかの GUI をセットアップしましたが、今、問題の核心であるデータベースのセットアップに直面しています。

私が設計した GUI では、次のように決めました。

図 1.0

伝説:

  • 緑色のチェック - 完了
  • オレンジ色- ユーザーは現在そのステップにいます
  • 灰色- 彼はそこにあるサブステップを開始していません。

写真が示すように、私は 3 つのトップレベルのプロシージャーと、各プロシージャーの下にいくつかの プロシージャーを持っています。この図に欠けていることの 1 つは、トップレベルの手順も特定のカテゴリの下にあるということです。

私が達成したいのは、ユーザーの活動を追跡することです。そして、ここに取引があります:

  1. 次の手順に進むために最初のトップレベルの手順を完了する必要はありません。スキップして戻ることができます -> これについては問題ありません。
  2. すべての子プロシージャーが完了すると、トップレベルのプロシージャーはその特定のユーザーに対して 1 のフラグを立てます。これは、それが完了したことを意味します。
  3. 同じことがカテゴリにも当てはまります。そのカテゴリの下のすべてのトップレベルの手順が完了すると、カテゴリはその特定のユーザーに対して 1 のフラグを立てます。これは、そのユーザーがカテゴリを完了したことを意味します。

そして、次のようにデータベースをセットアップする予定です。

-tbl_users-

 id    |    username    |    password    |
 -----------------------------------------
   1   |    some_user   |  adf8jkdfndsa  |
...

tbl_step_cat

 id    |      cat_name      |
 ---------------------------
   1   |    some_category   |
...

tbl_steps

 id    |      step_shortdesc     |    step_longdesc      |  cat_id 
 -------------------------------------------------------------------
   1   |      some step one      |  do the following...  |     1
 -------------------------------------------------------------------
   2   |      some step two      |  do the following...  |     1
 -------------------------------------------------------------------
   3   |      some step three    |  do the following...  |     2
...

tbl_substeps

 id    |     substep_shortdesc   |    substep_longdesc   |  step_id 
 -------------------------------------------------------------------
   1   |    some substep one     |  do the following...  |     1
 -------------------------------------------------------------------
   2   |    some substep two     |  do the following...  |     1
 -------------------------------------------------------------------
   3   |    some substep three   |  do the following...  |     1
 -------------------------------------------------------------------
   4   |    some substep a       |  do the following...  |     2
 -------------------------------------------------------------------
   5   |    some substep b       |  do the following...  |     2
 -------------------------------------------------------------------
   6   |    some substep 1       |  do the following...  |     3
...

そして、ユーザーとステップの間の関係テーブル

tbl_user_stepcat

 id    |     user_id   |    stepcat_id   |  datetime 
 -------------------------------------------------------------------
   1   |      1        |       1         |  sometime
 -------------------------------------------------------------------
   2   |      1        |       2         |  sometime
 -------------------------------------------------------------------

tbl_user_step

 id    |     user_id   |     step_id     |  datetime 
 -------------------------------------------------------------------
   1   |      1        |       1         |  sometime
 -------------------------------------------------------------------
   2   |      1        |       2         |  sometime
 -------------------------------------------------------------------

tbl_user_substep

 id    |     user_id   |    substep_id   |  datetime 
 -------------------------------------------------------------------
   1   |      1        |       1         |  sometime
 -------------------------------------------------------------------
   2   |      1        |       2         |  sometime
 -------------------------------------------------------------------

これが少し長い場合は申し訳ありませんが、コードが原因です。

今、私の質問は、どのようにして望ましい結果を返すかです。ご覧のとおり、ユーザーがアプリケーションにログインしたときに、それらの情報をすぐに表示できるようにします。

現時点では、脳がシャットダウンして焦点が合っていないため、試したことはありません。これまでのところ、これが私の最高の時間です.

このアプリケーションの SQL をコーディングするとしたら、もちろん複数の結合を行います。

最初にすべてのカテゴリを選択して、ユーザーに出力したいと考えています。

SELECT * FROM tbl_step_cat

これですべてのカテゴリが表示されます。次にやりたいことは、「スタイリング」を実行できるように、どのステップが完了しているかどうかを調べることです。

私はするかもしれません

SELECT cat_name FROM tbl_step_cat JOIN
tbl_user_stepcat ON tbl_user_stepcat.stepcat_id = tbl_step_cat.id
...

集中力がなく、今は考えられません。これらを行うにはどうすればよいですか:

  1. すべての猫/ステップ/サブステップを出力します
  2. 関係テーブルにエントリがある人を取得します。これは、完了したことを意味します
  3. どこuser = session['user']

どうもありがとう、私はちょうどガイダンスが必要でした.

4

5 に答える 5

5

わかりました。JOIN を指定するだけの場合、それは INNER JOIN になるため、ユーザーが各ステップとサブステップを完了していない結果は除外されます。したがって、結合ごとに確実に結果を取得できるようにするには、LEFT JOIN にします。これにより、null の結果と結合される場合があります。これは、サブカテゴリ フィールドが null であるかどうかをテストして、フォームに目盛りの部分を入力することができるため、問題ありません。

すべてをすべてに結合する 1 つの巨大なクエリをコーディングしようとするのではなく、データベース ロジックを個別のクエリに分割しても害はないと常に信じてきましたが、これは過剰かもしれません。

カテゴリごとに個別のクエリを実行すると思います。つまり、次のようになります。

(擬似)

SELECT * FROM CATEGORIES 
foreach (category) {
    SELECT * FROM SUBCATEGORIES WHERE CATEGORY = CATEGORYID
    foreach (SUBCATEGORY) {
        SELECT * FROM SUBSUBCATEGORIES WHERE SUBCATEGORY = SUBCATEGORYID
    }
}

そして、各ポイントでユーザー テーブルに対してクエリを実行して、リストを反復処理しながらユーザーが各ステップを完了したかどうかを確認し、そのループを使用して目盛りを設定します。

単一のメガ結合ほどエレガントではないかもしれませんが、それが好みでない場合は、理解を助けるためにクエリ ロジックを単純化しても問題はないと思います。

于 2013-01-09T14:47:54.437 に答える
3

テーブルは不要であり、user_stepcat冗長user_stepな情報のみが格納されるためです。

すべてcompletedの状態はサブステップの完了によってトリガーされ、このクエリによって取得できます

-- cat completed or not
SELECT
  sc.*, 
  MIN( IF( uss.substep_id IS NULL, 0, 1 ) ) completed,
  IF( MIN( IF( uss.substep_id IS NULL, 0, 1 ) ), 
    MAX( uss.datetime ), 
    NULL ) completed_at
FROM
  step_cat sc
LEFT JOIN steps s ON s.cat_id = sc.id
LEFT JOIN substeps ss ON ss.step_id = s.id
LEFT JOIN user_substep uss ON uss.user_id = 1 AND uss.substep_id = ss.id
GROUP BY sc.id;

-- steps completed or not
SELECT
  s.*, 
  MIN( IF( uss.substep_id IS NULL, 0, 1 ) ) completed,
  IF( MIN( IF( uss.substep_id IS NULL, 0, 1 ) ), 
    MAX( uss.datetime ), 
    NULL ) completed_at
FROM
  steps s
LEFT JOIN substeps ss ON ss.step_id = s.id
LEFT JOIN user_substep uss ON uss.user_id = 1 AND uss.substep_id = ss.id
GROUP BY s.id;

-- substeps completed or not
SELECT
  ss.*, 
  IF( uss.substep_id IS NULL, 0, 1 ) completed,
  uss.datetime completed_at
FROM
  substeps ss
LEFT JOIN user_substep uss ON uss.user_id = 1 AND uss.substep_id = ss.id;

SQLフィドルデモ

アップデート

GUIに関連する回答を提供するために、スクリーンショットに一致するようにサンプルデータを更新しました。

プレゼンテーションでは、現在のユーザーID、カテゴリID、およびステップIDを知っている必要があります

SET @user_id = 1; -- actual user
SET @cat_id = 1; -- actual category
SET @step_id = 2; -- actual step

現在のカテゴリと完全な状態を次のように取得できます

SELECT
  sc.*, 
  MIN( IF( uss.substep_id IS NULL, 0, 1 ) ) completed,
  IF( MIN( IF( uss.substep_id IS NULL, 0, 1 ) ), MAX( uss.datetime ), NULL ) completed_at
FROM
  step_cat sc
LEFT JOIN steps s ON s.cat_id = sc.id
LEFT JOIN substeps ss ON ss.step_id = s.id
LEFT JOIN user_substep uss ON 
-- limit to user
uss.user_id = @user_id 
AND uss.substep_id = ss.id
-- limit to cat
WHERE sc.id = @cat_id
GROUP BY sc.id;

カテゴリのステップとこれで完了した状態

SELECT
  s.*, 
  MIN( IF( uss.substep_id IS NULL, 0, 1 ) ) completed,
  IF( MIN( IF( uss.substep_id IS NULL, 0, 1 ) ), MAX( uss.datetime ), NULL ) completed_at
FROM
  steps s
LEFT JOIN substeps ss ON ss.step_id = s.id
LEFT JOIN user_substep uss
-- limit to user_id
ON uss.user_id = @user_id 
AND uss.substep_id = ss.id
-- limit to cat_id
WHERE s.cat_id = @cat_id
GROUP BY s.id;

少なくともサブステップとその完全な状態

SELECT
  ss.*, 
  IF( uss.substep_id IS NULL, 0, 1 ) completed,
  uss.datetime completed_at
FROM
  substeps ss
LEFT JOIN user_substep uss 
-- limit to user_id
ON uss.user_id = @user_id 
AND uss.substep_id = ss.id
-- limit to step_id
WHERE ss.step_id = @step_id;

SQLフィドルデモ

この3つのクエリすべてを使用すると、GUIプレゼンテーションに必要なすべての情報が得られます。

于 2013-01-10T16:13:03.927 に答える
1

SQL スキーマが step_cat <- steps <- substeps のように見えるということですか?

その場合、テーブル tbl_user_stepcat および tbl_user_step は、JOIN クエリを使用して特定のサブステップ/ステップ/cat からすべての親情報を取得できるため、役に立ちません。

ユーザーの実績を追跡したい場合は、ユーザー、サブステップ、および実績に応じて特定の値をとる可能性のある定義されたステータスに焦点を当てた「achievement_history」テーブルが必要です。このように、各行は特定のユーザーのサブステップの成果を参照し、特定のサブステップが正しい成果ステータスを持つたびに、ユーザーは別のサブステップを処理できるようになり、新しい行が挿入されます。

ネストされたクエリを使用することは、DBMS がクエリを計画することができず、インデックスと外部キーが正しく設定されている場合はそれらを使用して、すばやく結果を取得するための事前定義された方法を保存することができないため、非常に厄介な方法であることに注意してください。 .

于 2013-01-13T20:57:40.967 に答える
1

あなたは今、おそらくデータベース構造に集中しすぎているでしょう:

  • ステップ バイ ステップの手順のステップ ページを表示している場合は、ステップが終了したかどうかを確認できます。ステップのステータスを更新します。
  • ステップページにいる場合、このステップが含まれるすべてのステップを照会することもできます。単一のステップページにアクセスしたときにデータを最新の状態に保つと、ステップのステータスを表示するだけで済みます。
  • ステップバイステップの手順がない場合は、すべてのステップを一度に更新する必要がありますが、ステップバイステップの手順を初めて入力するときだけです。
  • ステップが他の成果と似ている場合、それは他の成果と似ています。ステップの構成データをアチーブメント (単一のステップ) から除外します。

次に、データベース構造をより柔軟に保ちながら、達成システムの手順を再利用しやすくすることができます。

たとえば、私があなたの質問を正しく読んだ場合、誰かがステップキャットと呼ぶもののカテゴリ全体を終了した場合に、ある日、成果を作成したいと決めた場合。

あなたがする必要があるのは、 1 つまたはn 個の成果が完了したかどうかを確認することだけです。そのため、他の実績で構成されているかどうかに関係なく、すべての実績を 1 つのテーブルにまとめてください)。これは別の場所に属します。カテゴリーと同じです。

一般的な方法は、データを部分的に非正規化することです。たとえば、要素化された処理が機能するデータをそこに保存するために、各実績に自由なテキストを保持できます。

用務員ジョブを実行してデータを整理し、高次の成果を確認し忘れていないかどうかを確認します。処理でエラーを導入した最初の瞬間に、完全に正規化された形式では制約に違反していなくてもデータが壊れるため、とにかくそれを行う必要があります。とにかく、その「手動」チェックを行う必要があります。

これらすべてのために、ただそれをしてください。頭を抱え込みすぎず、シンプルに、仕事を終わらせてから、改善を考えましょう。私ができる最初の提案は、多くの間違いを犯さないように物事をシンプルに保つことです。システムには、ここでの回答ではカバーできない専門分野があります。

したがって、必要なのは次のとおりです。

  1. 実績を定義する表を用意する
  2. ユーザーがアチーブメントを完了したかどうかを格納するテーブルを用意します。
  3. アチーブメントが完了したかどうかを判断できる処理を行います。
  4. アチーブメントを完了するための処理を行います。

その間:

  • マルチステップフォームの各ステップも成果です。

マルチステップであるかどうかは、あまり興味深いものではありません。それは単なる標準的な成果です。それが最大のメリットでしょう。データ構造ではなく、処理に違いをカプセル化します。これにより、現在および将来の採用が可能になります。

于 2013-01-13T13:40:50.443 に答える
1

バックエンドで 3 つのストアド プロシージャを記述し、フロント エンドからの入力 Session[Username] でそれらを呼び出す必要があります。

storedprocedure1 .. listofcategories.. 入力 - なし、出力 - カテゴリ属性

storedprocedure2.. listofcategories_filtered_by_user.. 入力 - セッション [ユーザー名] 出力 - カテゴリ属性

このストアド プロシージャ内に、あなたが書いた結合を記述します SELECT cat_name FROM tbl_step_cat JOIN tbl_user_stepcat ON tbl_user_stepcat.stepcat_id = tbl_step_cat.id

storedprocedure3.. listofsubcategories_filtered_by_user.. 入力 - セッション[ユーザー名] 出力 - (サブカテゴリ属性)

このストアド プロシージャ内に、サブカテゴリの結合を記述します。

> 次に、入力 Session[UserName] パラメータを使用して、フロントエンドから各ストアドプロシージャを呼び出します

于 2013-01-14T10:39:49.437 に答える