1

私が持っているテーブルと私が目指している結果から始めるのが最も簡単だと思います.

Name | Date
A    | 03/01/2012
A    | 03/01/2012
B    | 02/01/2012
A    | 02/01/2012
B    | 02/01/2012
A    | 02/01/2012
B    | 01/01/2012
B    | 01/01/2012
A    | 01/01/2012

クエリの結果を次のようにしたい:

Name | 01/01/2012 | 02/01/2012 | 03/01/2012
A    |     1      |     2      |     2
B    |     2      |     2      |     0

したがって、基本的には、同じ日付を持つ行の数を数えたいと思いますが、個々の名前ごとです。したがって、名前を一緒にマージするため、日付による単純なグループ化はできません。そして、PHPを使用して、個々の日付ごとのカウントを示すテーブルを出力したいと思います.

私は答えが次のようなことを示唆しているのを見てきました:

SELECT
  NAME,
  SUM(CASE WHEN GRADE = 1 THEN 1 ELSE 0 END) AS GRADE1,
  SUM(CASE WHEN GRADE = 2 THEN 1 ELSE 0 END) AS GRADE2,
  SUM(CASE WHEN GRADE = 3 THEN 1 ELSE 0 END) AS GRADE3
FROM Rodzaj
GROUP BY NAME

だから私はそれを微調整する方法があると思いますが、別の方法があるかどうか疑問に思っていましたか、それとも最も効率的ですか? while ループが毎回特定の名前と日付を 1 つだけ出力し、カウントとともに出力する場合、最初の結果は A,01/01/2012,1 になり、次の A,02/01/2012 になるのではないかと考えていました。 2 - A,03/01/2012,3 - B,01/01/2012,2 などの場合、別の手法で実行できる可能性がありますが、そのようなことが可能かどうか、効率的かどうかはわかりません。

だから私は基本的に誰かがこれについて少し枠の外にあるアイデアを持っているかどうか、そしてそれらがどのように比較されるかを探しています.

すべてを十分に説明したことを願っています。事前に助けてくれてありがとう。

4

3 に答える 3

2

あなたは「ピボット」を求めています。基本的に、それはそれが何であるかです。ピボットの本当の問題は、列がデータに適応しなければならないことであり、これは SQL だけでは不可能です。

方法は次のとおりです。

SELECT
  Name,
  SUM(`Date` = '01/01/2012') AS `01/01/2012`,
  SUM(`Date` = '02/01/2012') AS `02/01/2012`,
  SUM(`Date` = '03/01/2012') AS `03/01/2012`
FROM mytable
GROUP BY Name

mysql ではisおよびisであるためSUM()、mysql で条件を指定できるクールな方法に注意してください。したがって、条件を合計することは、それが真である回数を数えることと同じです。true1false0

最初に内部グループを使用することは効率的ではありません。

于 2012-08-04T19:24:22.937 に答える
2

に 2 つの列を含める必要がありますGROUP BY

SELECT   name, COUNT(*) AS count
FROM     your_table
GROUP BY name, date

これにより、各名前 -> 日付の組み合わせの数が行形式で取得されます。0名前に特定の日付の行がない場合にもカウントを含めたいので、次を使用できます。

SELECT     a.name,
           b.date,
           COUNT(c.name) AS date_count
FROM       (SELECT DISTINCT name FROM your_table) a
CROSS JOIN (SELECT DISTINCT date FROM your_table) b
LEFT JOIN  your_table c ON a.name = c.name AND 
                           b.date = c.date
GROUP BY   a.name, 
           b.date

SQLFiddle デモ

于 2012-08-04T19:15:41.437 に答える
0

誰かが最善の方法に興味を持っている場合に備えて:

Zane の 2 番目の提案は最も遅く、他の 2 つのデータの 3 分の 1 をロードしたところ、かなり時間がかかりました。おそらく、小さなテーブルではより効率的でしょう。私は巨大なテーブルで作業していませんが、約 28,000 行でかなりのラグが発生し、その間の句で結果が約 4000 行に落ちました。

ボヘミアンの答えは、コードの量を最小限に抑え、ループを投げてすべてのケースステートメントを作成し、比較的簡単に機能しました。このメソッドの利点は、ケースのループを作成するだけでなく、php のトリックを必要とせずに結果が得られる単純さでした。単純な foreach ですべての列を取得するだけです。phpに自信がない方におすすめです。

しかし、私は Zane の最初の提案が最も速く実行できることを発見し、追加の php コーディングが必要であるにもかかわらず、私はこの方法に固執するようです. この方法の欠点は、実際にデータがある日付のみを提供するため、すべての日付を含むテーブルを作成するのが少し複雑になることです。私がしたことは、各テーブル行でリセットされるテーブル列と比較されるはずの日付を追跡する変数を作成することでした。クエリの結果がその日付と等しい場合、値をエコーし​​、それ以外の場合は日付が一致するまで、表のセルを 0 でエコーする while ループ。また、「名前」の値が同じかどうかを確認する必要があり、そうでない場合は、行の最後まで欠落しているセルを 0 で埋めた後、次の行に切り替えます。

3 か月間のデータに対する 2 つの方法の結果 (各日の列なので、約 90 のケース ステートメント) ~ 28,000 のうちの 12,000 行:
Bohemian's Pivot - ~0.158 秒 (最高値 ~0.36 秒)
Zane's Double Group by - ~0.086 秒(最高値 ~0.15 秒)

于 2012-08-07T18:04:42.243 に答える