2

私はこの問題で立ち往生しています。

基本的に、私は各部門について、どの日に最も多くの売上があったかを把握する方法を見つける必要があります。結果には部門番号とその日の日付が表示され、同じように売上が最も多い日が数日あった場合は、部門番号が結果に数回表示される可能性があります。

これは私がこれまでに持っているものです:

SELECT departmentNo, sDate FROM Department
HAVING MAX(sDate)
ORDER BY departmentNo, sDate;

max関数を使用して、最も発生した日付を見つけてみました。ただし、1行の値しか返しません。さらに明確にするために、売上が最も多い日付は、departmentNoという対応する列に表示する必要があります。また、部門Aの2つの日付の売上が最も多い場合、部門Aは2回表示され、両方の日付も表示されます。

注:売上が最も多い日付と部門番号のみが表示されます。

私は数週間mySQLを開始しましたが、サブクエリやストア関数などを把握するのにまだ苦労しています。しかし、私は経験から学びます。前もって感謝します。

更新しました:

私が得るべき結果:

DepartmentNo Column 1: 1 | Date Column 2: 15/08/2000 
DepartmentNo Column 1: 2 | Date Column 2: 01/10/2012 
DepartmentNo Column 1: 3 | Date Column 2: 01/06/1999 
DepartmentNo Column 1: 4 | Date Column 2: 08/03/2002 
DepartmentNo Column 1: nth | Date Column 2: nth date

これらはデータです:

INSERT INTO Department VALUES ('1','tv','2012-05-20','13:20:01','19:40:23','2');
INSERT INTO Department VALUES ('2','radio','2012-07-22','09:32:23','14:18:51','4');
INSERT INTO Department VALUES ('3','tv','2012-09-14','15:15:43','23:45:38','3');
INSERT INTO Department VALUES ('2','tv','2012-06-18','06:20:29','09:57:37','1');
INSERT INTO Department VALUES ('1','radio','2012-06-18','11:34:07','15:41:09','2');
INSERT INTO Department VALUES ('2','batteries','2012-06-18','16:20:01','23:40:23','3');
INSERT INTO Department VALUES ('2','remote','2012-06-18','13:20:41','19:40:23','4');
INSERT INTO Department VALUES ('1','computer','2012-06-18','13:20:54','19:40:23','4');
INSERT INTO Department VALUES ('2','dishwasher','2011-06-18','13:20:23','19:40:23','4');
INSERT INTO Department VALUES ('3','lawnmower','2011-06-18','13:20:57','20:40:23','4');
INSERT INTO Department VALUES ('3','lawnmower','2011-06-18','11:20:57','20:40:23','4');
INSERT INTO Department VALUES ('1','mobile','2012-05-18','13:20:31','19:40:23','4');
INSERT INTO Department VALUES ('1','mouse','2012-05-18','13:20:34','19:40:23','4');
INSERT INTO Department VALUES ('1','radio','2012-05-18','13:20:12','19:40:23','4');
INSERT INTO Department VALUES ('2','lawnmowerphones','2012-05-18','13:20:54','19:40:23','4');
INSERT INTO Department VALUES ('2','tv','2012-05-12','06:20:29','09:57:37','1');
INSERT INTO Department VALUES ('2','radio','2011-05-23','11:34:07','15:41:09','2');
INSERT INTO Department VALUES ('1','batteries','2011-05-21','16:20:01','23:40:23','3');
INSERT INTO Department VALUES ('2','remote','2011-05-01','13:20:41','19:40:23','4');
INSERT INTO Department VALUES ('3','mobile','2011-05-09','13:20:31','19:40:23','4');

部門1の場合、日付2012-05-18が最も多く発生したため、その日付が表示されます。また、すべての部門について、売上が最も多い部門のみを表示する必要があります。同じ日に同じ売上高が表示される場合は、両方が表示されます。たとえば、部門1は、両方の最大売上の日付で2回表示されます。

4

2 に答える 2

2

サンプルデータとともに提供したテーブルと2つの列に基づいて、次のクエリをテストしました。それで、あなたのためにそれを説明させてください。最も内側の「PREQUERY」は、部門と日付でカウントしています。この結果は、最初に部門によって事前注文され、次に降順で最大のカウントが表示されます(したがって、最大の販売カウントが最初にリストされます)。カウントが発生した日付は関係ありません。

次に、MySQL @variablesを利用して、クエリで使用する2つを事前に宣言します。@variablesは、MySQLを使用したインラインプログラミングのようなものです。これらは一度宣言してから、処理中の各レコードに適用されるように変更できます。したがって、デフォルトでは、偽の部門の値とゼロの販売数になります。

ここで、PreQueryの結果(Dept、#Sales、およびDate)を取得していますが、テストを追加しています。特定の部門の最初のエントリである場合は、そのレコードの「NumberOfSales」を使用して@maxSales変数に入れ、最後の列名「MaxSaleCnt」として格納します。次の列名は@lastDeptを使用し、現在のレコードの部門番号に設定されます。したがって、次のレコードと比較できます。

次のレコードが同じ部門である場合、@ maxSales値が前の値と同じであるため、それぞれの部門のすべてのエントリに対して同じ最初のcount(*)結果が保持されます。

さて、閉鎖。HAVING句を追加しました(テストされるレコードを制限するWHEREではありませんが、レコードがPROCESSEDセットの一部になった後、HAVINGプロセスが実行されます。これで、5つの列すべてが含まれるようになります。レコードの最終的なNumberOfSalesは、部門のMaxSaleCntと一致します。1つ、2つ、またはそれ以上の日付の場合、問題なく、それぞれの部門ごとにすべてが返されます。

したがって、1つの部門にはそれぞれ10の売上がある5つの日付があり、別の部門にはそれぞれ3つの売上がある2つの日付があり、別の部門には6つの売上がある1つの日付しかない可能性があります。

select
      Final.DepartmentNo,
      Final.NumberOfSales,
      Final.sDate
   from
      (select
          PreQuery.DepartmentNo,
          PreQuery.NumberOfSales,
          PreQuery.sDate,
          @maxSales := if( PreQuery.DepartmentNo = @lastDept, @maxSales, PreQuery.NumberOfSales ) MaxSaleCnt,
          @lastDept := PreQuery.DepartmentNo
       from
          ( select
                  D.DepartmentNo,
                  D.sDate,
                  count(*) as NumberOfSales
               from
                  Department D
               group by
                  D.DepartmentNo,
                  D.sDate
               order by
                  D.DepartmentNo,
                  NumberOfSales DESC ) PreQuery,
          ( select @lastDept := '~',
                   @maxSales := 0 ) sqlvars
       having
          NumberOfSales = MaxSaleCnt ) Final

最後のコメントごとに「@」と「〜」を明確にします。「@」は、クエリで使用できるプログラムのローカル変数(この場合はインラインSQL変数)を示します。'〜'は、どの部門の確率も存在しないという単純な文字列にすぎないため、最初の修飾レコードと比較するときに、IF('〜' = YourFirstDepartmentNumberを実行し、それ以外の場合はこの回答を使用します。この回答を使用してください)。

さて、上記はどのように機能しますか。以下は、最も内側のクエリによって返されたデータの結果であり、上位の売上が最も多い順にグループ化および順序付けされているとしましょう...データからわずかに変更され、次のように仮定して、部門の複数の日付をシミュレートします。同じ販売数量の2..。

Row#   DeptNo  Sales Date     # Sales
1      1       2012-05-18        3
2      1       2012-06-18        2
3      1       2012-05-20        1

4      2       2012-06-18        4
5      2       2011-05-23        4
6      2       2012-05-18        2
7      2       2012-05-12        1

8      3       2011-06-18        2
9      3       2012-09-14        1

実際の行を追跡します。エイリアス「PreQuery」として終了する最も内側のクエリは、ここに表示されている順序ですべての行を返します。次に、それは@ sqlvariablesの宣言と結合(暗黙)され(MySQLに特別で、他のsqlエンジンはこれを行いません)、la​​stDept ='〜'およびmaxSales = 0(@someVariableでの割り当てを介して)で値を開始します。 =こちら側の結果)。さて、上記が次のように扱われていると考えてください

DO WHILE WE HAVE RECORDS LEFT
   Get the department #, Number of Sales and sDate from the record.

   IF the PreQuery Record's Department # = whatever is in the @lastDept
      set MaxSales = whatever is ALREADY established as max sales for this dept
      This basically keeps the MaxSales the same value for ALL in the same Dept #
   ELSE
      set MaxSales = the # of sales since this is a new department number and is the highest count
   END IF

   NOW, set @lastDept = the department you just processed to it 
   can be compared when you get to the next record.

   Skip to the next record to be processed and go back to the start of this loop
END DO WHILE LOOP

ここで、返される列として@MaxSalesとTHEN @LastDeptが必要な理由は、NEXTレコードとの比較に使用するレコードごとに計算する必要があるためです。この手法は、多くのアプリケーション目的に使用できます。私の名前をクリックし、私のタグを見て、MySQLタグをクリックすると、私が応答した多くのMySQLの回答が表示されます。それらの多くは@sqlvariablesを利用します。さらに、クエリの処理が非常に得意な人は他にもたくさんいるので、1か所だけを見てはいけません。質問については、質問を投稿していなくても、役立つと思われる良い回答を見つけた場合は、回答の横にある上向き矢印をクリックすると、他の人が質問を理解して解決するのに本当に役立ったものを示すのに役立ちます- -繰り返しますが、それがあなたの質問でなくても。MySQLの成長に頑張ってください。

于 2012-12-01T04:33:30.253 に答える
1

これは単一のクエリで実現できると思いますが、同様の機能に関する私の経験では、OracleまたはMSSQLのいずれかを使用したWITH(SQL'99で定義)のいずれかが関係しています。

このような問題に取り組むための最良の(唯一の?)方法は、より小さなコンポーネントに侵入することです。(提供されたステートメントがすべての列を提供するとは思わないので、いくつかの仮定を行う必要があります。)

まず、各グループの1日あたりの売上高は次のとおりです。

SELECT department, COUNT(1) AS dept_count, sale_date
FROM orders
GROUP BY department, sale_date

次に、各部門の売上高はどれくらいですか

SELECT tmp.department, MAX(tmp.dept_count)
FROM (
    SELECT department, COUNT(1) AS dept_count
    FROM orders
    GROUP BY department
) AS tmp
GROUP BY tmp.department

最後に、2つをまとめます。

 SELECT a.department, a.dept_count, b.sale_date
 FROM (
    SELECT tmp.department, MAX(tmp.dept_count) AS max_dept_count
    FROM (
       SELECT department, COUNT(1) AS dept_count
       FROM orders
       GROUP BY department
    ) AS tmp
    GROUP BY tmp.department
 ) AS a
 JOIN (
    SELECT department, COUNT(1) AS dept_count, sale_date
    FROM orders
    GROUP BY department, sale_date
 ) AS b
    ON a.department = b.department
       AND a.max_dept_count = b.dept_count
于 2012-12-01T02:08:17.043 に答える