私はケープタウンのホームレス団体で働いています。 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#
これは、「ピボット」テクニックの魔法に大きく依存します。 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()
は、評価されたすべての行の最大値を選択し、空の文字列または日付文字列を返します。分離された値が空の文字列と等しい場合、SubmissionId
はSELECT
句の対象となります。
SELECT
句では、同じ集合フィルタリングテクニックを再び使用して、結果セットで配信する値を決定します。
個々の人々、性別、現在のシェルターを分離するために、シェルターを退出した人々を除外する単純なピボットクエリを次に示します。
_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ピボットの回答もいくつかあります。 1 、 2 、、 4 、 5 、 6 、 7 、 8 、 9 、 1 。私は自由な仕事をやりすぎないようにしたくありませんが、再び行き詰まった場合は、遠慮なく別の質問をしてください。
追伸CASE
ブロックの調査と発見を続けると、SQLのIF()
ブロックと同じ動作になります。構文は少し異なりますが、IF
とCASE
は同じ意味で使用してください。
_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
_にも変換する必要があります。これは短期的には痛みを伴いますが、長期的な利点は、クエリを読みやすく維持しやすく、クエリ実行ごとのパフォーマンスが向上する、無駄のないクリーンなクエリになります。データベースは大きくなるだけなので、これは重要な仕事です。将来、多くの頭痛の種を避け、日付の値を整理してください。