web-dev-qa-db-ja.com

VChartおよび/またはPlotaLotにmysqlを使用したRSFORMのチャート/グラフ

私はケープタウンのホームレス団体で働いています。 RSFormsを使用してクライアントを登録しています(年間約3500)。かなり大きなデータベースがありますが、ダッシュボードを作成するのは非常に困難です。

Vchartまたはplotalotを使用しようとしていますが、MySQLに関する十分な知識がなく、JSEで見つかった例以上のものを入手できません。これはすでにハイエンドです: RSForm Proの結果に基づいてPlotALotグラフの凡例にゼロ値を表示する方法

これを使用しましたが、クエリのさまざまな部分がどのように機能するかは実際にはわかりません。別の実用的な例があれば、他のことを自分で解決できるかもしれません。

SELECT FieldValue, COUNT(1)
FROM jprefix_rsform_submission_values
WHERE FormId = 14
  AND FieldName = 'SHELTER'
GROUP BY 1
ORDER BY 2 DESC

PlotALotまたはMYSQLに基づいてビジュアルを作成するその他のサードパーティでテーブル(行と列を含む)または円グラフを抽出できたら素晴らしいと思います。例:SHELTERごとに(CLIENTIDに基づいて)現在の(終了日がない)かどうかに応じて人数をカウントします

GENDERの数をシェルターごとに分割できれば、さらに大きくなります。したがって、結果が表示されます:SHELTERを男性/女性で割り、現在のCLIENTIDに基づいてカウントするため、終了日はありませんが、開始日があります

ここでデータベースの例を見つけることができます:
https://www.db-fiddle.com/f/p84yz8fmHQAQtuF8uUReFY/0#

1
Gart

これは、「ピボット」テクニックの魔法に大きく依存します。 https://joomla.stackexchange.com/questions/tagged/pivot と比較/対比するためのJSEのいくつかの例を次に示します。

基本的に、WHERE句はグループ化が行われる前に行を失格にします。この場合、FormId _14_のスコープ内のデータのみに焦点を当てたいので、これはWHERE句に含める必要があります。

次に、すべてのデータを、フォームを送信した1人のユーザーに「添付/関連」させる必要があります。したがって、FormId _14_行をSubmissionIdでグループ化する必要があります。

次に、SubmissionIds値として空の文字列を持たないEXITDATEを失格にする必要があります。これは、一部の人々がパニックしたり、混乱したりする場所です。深呼吸、理解することは不可能ではありません。

_GROUP BY_が呼び出された後、_GROUP BY_宣言にリストされていないすべての列データは「集約データ」になります。つまり、グループ化された列はSELECT句で直接使用できます。論理的には、その列には値が1つしかないためです。残りのデータについては、これらの行をデータの「クラスター/クラウド/質量」と考えてください。これらのデータの非特異部分の処理に役立つ専用の関数があります。 https://www.mysqltutorial.org/mysql-aggregate-functions.aspx

HAVING句はWHERE句と同様に動作しますが、グループ化が行われた後でのみ、フィルタリングを開始します。次に、IF()条件がデータの「行」ごとに実行されます。集計データ内の既知の行の位置を分離する方法がないため、すべての行のFieldName値をチェックして、FieldValueが実際に目的の値であることを確認する必要があります。集計内のすべての行はNULL(条件式のスコープ内)として評価され、EXITDATE値のみがNULL以外になります。 MAX()は、評価されたすべての行の最大値を選択し、空の文字列または日付文字列を返します。分離された値が空の文字列と等しい場合、SubmissionIdSELECT句の対象となります。

SELECT句では、同じ集合フィルタリングテクニックを再び使用して、結果セットで配信する値を決定します。


TL; DR ...アカデミアで十分です。実用にしましょう。

個々の人々、性別、現在のシェルターを分離するために、シェルターを退出した人々を除外する単純なピボットクエリを次に示します。

_SELECT
    SubmissionId,
    MAX(IF(FieldName = 'SHELTER', FieldValue, NULL)) AS Shelter,
    MAX(IF(FieldName = 'GENDER', FieldValue, NULL)) AS Gender
FROM o2pe0_rsform_submission_values
WHERE FormId = 14
GROUP BY SubmissionId
HAVING MAX(IF(FieldName = 'EXITDATE', FieldValue, NULL)) = ''
_

出力:(SubmissionIdは、データの相対性を示すためにSELECTにのみリストされています)

_| SubmissionId | Shelter    | Gender |
| ------------ | ---------- | ------ |
| 46978        | Mossel Bay | Male   |
| 46979        | Mossel Bay | Male   |
| 46980        | Mossel Bay | Female |
| 47013        | Swartland  | Male   |
| 47014        | Swartland  | Male   |
| 47015        | Swartland  | Male   |
| 47016        | Bellville  | Male   |
| 47017        | Bellville  | Male   |
_

データを匿名化するには、Shelterでグループ化し、Gendersをカウントします。上記のピボットを使用して、Ithinkとしてカウントします。サブクエリは賢明な選択です(私は代替案について考えるのに十分な時間を費やしていません)。

_SELECT
    Shelter,
    Gender,
    COUNT(*) AS People
FROM (
  SELECT
      MAX(IF(FieldName = 'SHELTER', FieldValue, NULL)) AS Shelter,
      MAX(IF(FieldName = 'GENDER', FieldValue, NULL)) AS Gender
  FROM o2pe0_rsform_submission_values
  WHERE FormId = 14
  GROUP BY SubmissionId
  HAVING MAX(IF(FieldName = 'EXITDATE', FieldValue, NULL)) = ''
) DerivedTable
GROUP BY Shelter, Gender
ORDER BY People DESC, Shelter, Gender
_

出力:

_| Shelter    | Gender | People |
| ---------- | ------ | ------ |
| Swartland  | Male   | 3      |
| Bellville  | Male   | 2      |
| Mossel Bay | Male   | 2      |
| Mossel Bay | Female | 1      |
_

データを匿名化するには、Shelterでグループ化し、リストされた2つのGendersを個別にカウントし、派生したMale列とFemale列を個別に(ハードコード)割り当てます親SELECTの列値を合計する前にピボットテーブル。

_SELECT
    Shelter,
    SUM(Females) AS Females,
    SUM(Males) AS Males
FROM (
  SELECT
      MAX(IF(FieldName = 'SHELTER', FieldValue, NULL)) AS Shelter,
      MAX(IF(FieldName = 'GENDER' AND FieldValue = 'Male', 1, 0)) AS Males,
      MAX(IF(FieldName = 'GENDER' AND FieldValue = 'Female', 1, 0)) AS Females
  FROM o2pe0_rsform_submission_values
  WHERE FormId = 14
  GROUP BY SubmissionId
  HAVING MAX(IF(FieldName = 'EXITDATE', FieldValue, NULL)) = ''
) DerivedTable
GROUP BY Shelter
ORDER BY Shelter, Females, Males
_

出力:

_| Shelter    | Females | Males |
| ---------- | ------- | ----- |
| Bellville  | 0       | 2     |
| Mossel Bay | 1       | 2     |
| Swartland  | 0       | 3     |
_

これでプロジェクトを進めるのに十分だと思います。さらに例が必要な場合は、Stack Overflowピボットの回答もいくつかあります。 12 、、 4567891 。私は自由な仕事をやりすぎないようにしたくありませんが、再び行き詰まった場合は、遠慮なく別の質問をしてください。

追伸CASEブロックの調査と発見を続けると、SQLのIF()ブロックと同じ動作になります。構文は少し異なりますが、IFCASEは同じ意味で使用してください。


さて、さて、最後の1つのクエリ(ただし、この投稿に対する編集はこれ以上ありません)...

デモ

_SELECT
    Shelter,
    SUM(IF(MONTH(Entry) = MONTH(NOW()), Female, 0)) AS FemalesInLastMonth,
    SUM(IF(MONTH(Entry) = MONTH(NOW()), Male, 0)) AS MalesInLastMonth,
    SUM(Female) AS FemalesInLast3Months,
    SUM(Male) AS MalesInLast3Months
FROM (
  SELECT
      MAX(IF(FieldName = 'SHELTER', FieldValue, NULL)) AS Shelter,
      STR_TO_DATE(MAX(IF(FieldName = 'ENTRY', FieldValue, '01-01-1901')), '%d/%m/%Y') AS Entry,
      MAX(IF(FieldName = 'GENDER' AND FieldValue = 'Male', 1, 0)) AS Male,
      MAX(IF(FieldName = 'GENDER' AND FieldValue = 'Female', 1, 0)) AS Female
  FROM o2pe0_rsform_submission_values
  WHERE FormId = 14
  GROUP BY SubmissionId
  HAVING MAX(IF(FieldName = 'SHELTER', FieldValue, NULL)) = 'Mossel Bay'
     AND STR_TO_DATE(MAX(IF(FieldName = 'ENTRY', FieldValue, '01-01-1901')), '%d/%m/%Y') >= DATE(NOW() - INTERVAL 3 MONTH)
     AND MAX(IF(FieldName = 'EXITDATE', FieldValue, NULL)) = ''
) AS DerivedTable
GROUP BY Shelter
_

結果セット:(入力データが限られているため、それほど刺激的ではありません)

_| Shelter    | FemalesInLastMonth | MalesInLastMonth | FemalesInLast3Months | MalesInLast3Months |
| ---------- | ------------------ | ---------------- | -------------------- | ------------------ |
| Mossel Bay | 0                  | 0                | 0                    | 1                  |
_

MySQLの日付関数を使用すると毎回特別な準備が必要になるため、_d/m/Y_形式の日付文字列のクエリには回避可能な費用がかかることに注意してください。可能であれば、RSForm送信データを(人に優しい)代わりにMySQLに適した日付形式_YYYY-MM-DD_に変換し、既存のすべての日付値を_YYYY-MM-DD_にも変換する必要があります。これは短期的には痛みを伴いますが、長期的な利点は、クエリを読みやすく維持しやすく、クエリ実行ごとのパフォーマンスが向上する、無駄のないクリーンなクエリになります。データベースは大きくなるだけなので、これは重要な仕事です。将来、多くの頭痛の種を避け、日付の値を整理してください。

1
mickmackusa