每天从SQL DB中选择数据

时间:2009-08-13 20:11:28

标签: sql

我在电子商务商店中有一张包含订单信息的表格。架构看起来像这样:

[指令]
ID |小计| TAXAMOUNT | ShippingAmount | dateCreated会

此表仅包含每个订单的数据。因此,如果一天没有任何订单,则当天没有销售数据。

我想选择过去30天的每日小计,包括那些没有销售的日子。

结果集如下所示:

日期| SalesSum
2009-08-01 | 15235个
2009-08-02 | 0
2009-08-03 | 340个
2009-08-04 | 0
......

执行此操作,仅向我提供订单日期的数据:

select DateCreated as Date, sum(ordersubtotal) as SalesSum
from Orders
group by DateCreated

您可以创建一个名为Dates的表,然后从该表中选择并加入Orders表。但我真的想避免这种情况,因为在处理不同的时区和事情时它不够好......

请不要笑。 SQL不是我的事......:)

9 个答案:

答案 0 :(得分:2)

declare @oldest_date datetime
declare @daily_sum numeric(18,2)
declare @temp table(
    sales_date datetime,
    sales_sum numeric(18,2)
)
select @oldest_date = dateadd(day,-30,getdate())

while @oldest_date <= getdate()
begin
    set @daily_sum = (select sum(SubTotal) from SalesTable  where DateCreated = @oldest_date)
    insert into @temp(sales_date, sales_sum) values(@oldest_date, @daily_sum)
    set @oldest_date = dateadd(day,1,@oldest_date)
end

select * from @temp

好的 - 我错过了“过去30天”的部分。上面的位,虽然没有那么干净,恕我直言,作为日期表,应该工作。另一种变体是使用while循环来填充最近30天的临时表,并使用原始查询的结果执行左外连接。

答案 1 :(得分:2)

创建一个可以生成日期表的函数,如下所示:
(从http://www.codeproject.com/KB/database/GenerateDateTable.aspx偷来)

Create Function dbo.fnDateTable
(
  @StartDate datetime,
  @EndDate datetime,
  @DayPart char(5) -- support 'day','month','year','hour', default 'day'
)
Returns @Result Table
(
  [Date] datetime
)
As
Begin
  Declare @CurrentDate datetime
  Set @CurrentDate=@StartDate
  While @CurrentDate<=@EndDate
  Begin
    Insert Into @Result Values (@CurrentDate)
    Select @CurrentDate=
    Case
    When @DayPart='year' Then DateAdd(yy,1,@CurrentDate)
    When @DayPart='month' Then DateAdd(mm,1,@CurrentDate)
    When @DayPart='hour' Then DateAdd(hh,1,@CurrentDate)
    Else
      DateAdd(dd,1,@CurrentDate)
    End
  End
  Return
End

然后,加入该表

SELECT dates.Date as Date, sum(SubTotal+TaxAmount+ShippingAmount)
FROM [fnDateTable] (dateadd("m",-1,CONVERT(VARCHAR(10),GETDATE(),111)),CONVERT(VARCHAR(10),GETDATE(),111),'day') dates 
LEFT JOIN Orders
ON dates.Date = DateCreated
GROUP BY dates.Date

答案 2 :(得分:1)

  

包括那些没有销售的日子。

这是困难的部分。我不认为第一个答案可以帮助你。我用一个单独的日期表做了类似的事情。

您可以在此处找到有关如何操作的说明:

Date Table

答案 3 :(得分:1)

我有一个LogID表,LogID是一个索引,我永远不会删除任何记录。它的索引从1到10000000。使用这个表我可以写

select 
     s.ddate, SUM(isnull(o.SubTotal,0))
from 
    (
        select 
            cast(datediff(d,LogID,getdate()) as datetime) AS ddate 
        from
            Log 
        where 
            LogID <31
    ) s right join orders o on o.orderdate = s.ddate
group by s.ddate

答案 4 :(得分:0)

我今天真的这样做了。我们还有一个电子商务应用程序。我不想用“无用”的日期填充我们的数据库。我只是通过编写组来创建Java中最后N天的所有日子,并使用数据库中的日期/销售结果与它们进行对等。

答案 5 :(得分:0)

这最终会在哪里结束?我只是因为用任何程序来处理数据而不是试图在SQL中完成它来填充空白的日子可能更容易。

SQL是一种很棒的语言,它能够提供很多东西,但有时你最好不要在程序中处理更精细的数据点。

答案 6 :(得分:0)

(修改了一下 - 我很快就输入了)

我开始讨论这个问题,因为它遇到了一些非常棘手的SQL概念,它很快变成了下面的怪物。如果可行的话,你可能最好不要适应THEn的解决方案;或者像许多其他人一样建议,使用应用程序代码填补空白可能是首选。

--  A temp table holding the 30 dates that you want to check
DECLARE @Foo Table (Date  smalldatetime  not null)

--  Populate the table using a common "tally table" methodology (I got this from SQL Server magazine long ago)
;WITH
  L0 AS (SELECT 1 AS C UNION ALL SELECT 1), --2 rows
  L1 AS (SELECT 1 AS C FROM L0 AS A, L0 AS B),--4 rows
  L2 AS (SELECT 1 AS C FROM L1 AS A, L1 AS B),--16 rows
  L3 AS (SELECT 1 AS C FROM L2 AS A, L2 AS B),--256 rows
  Tally AS (SELECT ROW_NUMBER() OVER(ORDER BY C) AS Number FROM L3)
INSERT @Foo (Date)
 select dateadd(dd, datediff(dd, 0, dateadd(dd, -number + 1, getdate())), 0)
 from Tally
 where Number < 31

步骤1是构建一个临时表,其中包含您关注的30个日期。这种抽象的诡计是建立一个连续整数表的最快方法;添加一些子查询,您可以在几秒钟内填充数百万或更多。我取前30,并使用dateadd和当前日期/时间将它们转换为日期。如果你已经有一个1-30的“固定”表,你可以使用它并完全跳过CTE(通过用你的表替换表“Tally”)。

外部两个日期函数调用删除生成的字符串的时间部分。

(请注意,我假设您的订单日期也没有时间部分 - 否则您还有另一个常见问题需要解决。)

出于测试目的,我构建了表#Orders,这样就可以了解其余部分:

SELECT f.Date, sum(ordersubtotal) as SalesSum
 from @Foo f
  left outer join #Orders o
   on o.DateCreated = f.Date
 group by f.Date

答案 7 :(得分:0)

我创建了函数DateTable,正如JamesMLV指出的那样。

然后SQL看起来像这样:

SELECT dates.date, ISNULL(SUM(ordersubtotal), 0) as Sales FROM [dbo].[DateTable] ('2009-08-01','2009-08-31','day') dates
LEFT JOIN Orders ON CONVERT(VARCHAR(10),Orders.datecreated, 111) = dates.date
group by dates.date

答案 8 :(得分:-1)

SELECT DateCreated,
SUM(SubTotal) AS SalesSum
FROM Orders
GROUP BY DateCreated