2012-03-24 5 views
1

私は現在の52週のカウントを私に与えるように変更したいという質問があります。このクエリは、固定範囲内の日付のリストを含む私が作ったカレンダーテーブルを利用しています。クエリーは、最大および最小の日付を選択することであり、必ずしも最後の52週間である必要はありません。現在の52週間の週別のアイテム数をカウントするMySQLクエリ?

カレンダーテーブルを最新の状態に維持して、過去52週間(つまり、今から1年前まで)にすることができます。または、クエリをカレンダーテーブルを使用することから独立させる別の方法がありますか?

ここでクエリがあります:

SELECT calendar.datefield AS date, IFNULL(SUM(purchaseyesno),0) AS item_sales 
FROM items_purchased join items on items_purchased.item_id=items.item_id 
RIGHT JOIN calendar ON (DATE(items_purchased.purchase_date) = calendar.datefield) 
WHERE (calendar.datefield BETWEEN (SELECT MIN(DATE(purchase_date)) 
FROM items_purchased) AND (SELECT MAX(DATE(purchase_date)) FROM items_purchased)) 
GROUP BY week(date) 

考えですか?

+0

なぜカレンダーテーブルがあり、そのテーブルのDATEまたはDATETIME列を使用しているだけではないのですか? –

+0

カレンダーテーブルは、各期間ごとにビンが必要で、特定のビンのデータがない場合に使用されます。 –

+0

@ Ryan Kempt、それは実際にOPが求めているものかもしれません。また、日付の順序が必要な場合は、日付関数はそれほど役に立ちません。 –

答えて

1

一部の人々は、このアプローチを嫌うが、私は0からの値を含むダミーテーブルを使用する傾向がある - 1000年、その後、必要な範囲を生成するために派生テーブルを使用 -

CREATE TABLE dummy (`num` INT NOT NULL); 
INSERT INTO dummy VALUES (0), (1), (2), (3), (4), (5), .... (999), (1000); 

あなたがテーブルを持っている場合自動増分IDとそれから生成できる行がたくさんあります。 -

CREATE TABLE `dummy` 
SELECT id AS `num` FROM `some_table` WHERE `id` <= 1000; 

0の値を挿入してください。 @sql変数を使用して

SELECT WEEK(calendar.datefield) AS `week`, IFNULL(SUM(purchaseyesno),0) AS item_sales 
FROM items_purchased join items on items_purchased.item_id=items.item_id 
RIGHT JOIN (
    SELECT (CURRENT_DATE - INTERVAL num DAY) AS datefield 
    FROM dummy 
    WHERE num < 365 
) AS calendar ON (DATE(items_purchased.purchase_date) = calendar.datefield) 
WHERE calendar.datefield >= (CURRENT_DATE - INTERVAL 1 YEAR) 
GROUP BY week(datefield) -- shouldn't this be datefield instead of date? 
+0

こんにちはnnichols、ありがとう、私はこのショットを与えるでしょう、なぜこのアプローチのような人々はいないのですか?コードが醜く見えますか?またはクエリが遅いですか?または...? –

+0

私はなぜそれがわかりません。これに関するパフォーマンス上の問題は一切ありません。個人的には、それはむしろ洗練されたソリューションだと思います。 – nnichols

+0

私はダミーテーブルを作った。そのアドバイスをありがとう。しかし、私はあなたの声明に特に混乱していると思います: 'where calendar.datefield> =(CURRENT_DATE - INTERVAL 1 YEAR)'。カレンダーテーブルは2008年1月から2010年9月にかけています。平等によって、カレンダーテーブルを昨年も更新し続ける必要がありますか?ちなみに、あなたが 'group by week(datefield)'で、 'group by week(date)'ではなく、52週間の商品販売をしています。 'date'は定義されていません。しかし、52週間の商品販売が最新の52週間であるかどうかはまだわかりません。思考? –

1

私はあまりにも一般的にその場でテーブルを「シミュレート」とだけいずれかに参加 -

SELECT CURRENT_DATE - INTERVAL num DAY 
FROM dummy 
WHERE num < 365 

だから、あなたのクエリにこの方法を適用すると、あなたはこのような何かを行うことができますあなたのシステム内に、少なくともあなたが望む週数を持つテーブルがあります。注...日付を扱うとき、私は通常、日付部分のみを使用して、12:00:00を意味します。また、 "EndOfWeek"の開始日を7日前に進めることで、週単位の必要な時間帯などのレコードにBETWEEN句を適用できるようになりました。

私は週ごとに日付の関連付けに基づいて参加座標ためにそのようなサンプルを適用した...あなたの

select 
     DynamicCalendar.StartOfWeek, 
     COALESCE(SUM(IP.PurchaseYesNo), 0) as Item_Sales 
    from 
     (select 
       @weekNum := @weekNum +1 as WeekNum, 
       @startDate as StartOfWeek, 
       @startDate := date_add(@startDate, interval 1 week) EndOfWeek 
      from 
       (select @weekNum := 0, 
         @startDate := date(date_sub(now(), interval 1 year))) sqlv, 
       AnyTableThatHasAtLeast52Records, 
      limit 
      52) DynamicCalendar 
     LEFT JOIN items_purchased IP 
     on IP.Purchase_Date bewteen DynamicCalendar.StartOfWeek 
          AND DynamicCalendar.EndOfWeek 
    group by 
     DynamicCalendar.StartOfWeek 

これはあなたの「PurchaseYesNo」の値は、あなたの中にあるという前提の下にあるので、テーブルを直接購入しました。その場合は、ITEMSテーブルに参加する必要はありません。フィールドがアイテムテーブルにある場合は、アイテムテーブルのLEFT JOINをタックしてその値を取得します。

ただし、MANY条件でdynamicCalendarコンテキストを使用できます。

関連する問題