3

私はSalesテーブルを持っています:

id_item, quantity, date_time

必要なのは、1か月に販売されたアイテムを合計し、選択した月の期間の日で割ることです。

例-ユーザーが10月1日から12月31日までの日付を選択します。items_sold/days_of_monthを表示する必要があります。

Month  Items sold  Days of month  Items/Day
Sep        25           30           0.83333
Oct        36           31           1.16
Dec        15           31           0.4838

アイテムの種類で指定する必要があります。種類は、Itemsと呼ばれる別のテーブルから取得されます。私はdateformatを使用していますdd/mm/yy

select
   month(date_time),
   sum(quantity) / (select(datepart(dd,getdate())))
from
   sales v
   join items a on v.id_item=a.id_item
where
   a.kind='Kind of Item'
   and cast(Convert(varchar(10), date_time, 112) as datetime)
      between '01/10/2012' and '31/12/2012'
group by
   month(date_time)

私の問題は月の日を選択することですが、xの月数を選択し、各月の合計(数量)を各日で割るにはどうすればよいですか?

コードのこの部分は、当月の日のみを選択することを知っています。

(select(datepart(dd,getdate())))
4

1 に答える 1

4

サイズについてはこれを試してください:

DECLARE
   @FromDate datetime,
   @ToDate date; -- inclusive

SET @FromDate = DateAdd(month, DateDiff(month, 0, '20121118'), 0);
SET @ToDate = DateAdd(month, DateDiff(month, 0, '20121220') + 1, 0);

SELECT
    Year = Year(S.date_time),
    Month = Month(S.date_time),
    QtyPerDay =
       Sum(s.quantity) * 1.0
       / DateDiff(day, M.MonthStart, DateAdd(month, 1, M.MonthStart))
FROM
    dbo.Sales S
    INNER JOIN dbo.Items I
       ON S.id_item = I.id_item
    CROSS APPLY (
       SELECT MonthStart = DateAdd(month, DateDiff(month, 0, S.date_time), 0)
    ) M
WHERE
    I.kind = 'Kind of Item'
    AND S.date_time >= @FromDate
    AND S.date_time < @ToDate
GROUP BY
    Year(S.date_time),
    Month(S.date_time),
    M.MonthStart

とで部分的に囲まれている月全体が選択されFromDateますToDate。列が整数の場合はこの* 1.0部分が必要です。そうでない場合は、10進数ではなく整数の結果が得られます。quantity

いくつかの文体のメモ:

  • 丸一日を確実に取得するために、列で文字列の日付変換を使用しないでください。これにより、インデックスの使用が完全に防止され、より多くのCPUが必要になり、さらに不明確になります(スタイル112は再び何をしますか!?!?)。DateCol >= StartDate完全な日付期間を囲むには、とのクエリで示したものを使用しますDateCol < OneMoreThanEndDate。ここで非常に重要な概念を理解するには、「sargable」を検索してください。非常に安全で価値のある一般的なルールは、条件を書き直して回避できる場合は、式の中に列を入れないことです。

  • テーブルのエイリアスを作成するのは良いことですが、クエリで行ったように、各列のクエリ全体でこれらのエイリアスを使用する必要があります。エイリアスVとAは別の言語からのものであるため、そこでは意味があります。通常は、テーブル名と一致するエイリアスを使用してみてください。

  • オブジェクトにスキーマ名を含めてください。そうしないことは大きなノーノーではありませんが、明確な利点があり、それがベストプラクティスです。

  • 質問するときは、すべてのロジックを説明して、ユーザーが推測したり質問したりする必要がないようにすることが役立ちます。たとえば、ユーザーが月の半ばの日付を入力できることがわかっているが、1か月が必要な場合は、次のように示してください。あなたの質問で、何をする必要があるかを述べてください。

  • SQL Serverのバージョンを指定すると、以前のバージョンでは表現力が低下するため、必要な構文に焦点を合わせるのに役立ちます。バージョンをお知らせいただくことで、可能な限り最高のクエリを提供できます。

注:日付計算の計算をクエリ自体に含めることには何の問題もありません(SETを使用して計算する代わりに)。しかし、これをストアドプロシージャでエンコードすることになると思いました。その場合は、SETを使用しても問題ありません。

于 2012-12-20T19:54:18.930 に答える