帮我解决这个SQL查询

时间:2010-07-27 00:34:30

标签: sql sql-server-ce

我有一个带有以下架构的SQL Server CE 3.5表(交易):

  • ID
  • TRANSACTION_DATE
  • 分类
  • 描述
  • 金额

查询:

  SELECT Transaction_Date, SUM(Amount) 
    FROM Transactions 
GROUP BY Transaction_Date;

我正在尝试通过transaction_date执行SUM(金额)和分组,这样我就可以获得每天的总金额但是我想要获取值甚至几天没有交易所以基本上是一天的记录没有交易只需要0.00美元的金额。

感谢您的帮助!

5 个答案:

答案 0 :(得分:0)

您需要一个日历表来选择日期。或者,如果您有Numbers表,则可以将其有效地转换为Calendar表。基本上,它只是一个包含每个日期的表格。它很容易为它构建和生成数据,并且在这些情况下非常方便。然后你只需使用:

SELECT
    C.calendar_date,
    SUM(T.amount)
FROM
    Calendar C
LEFT OUTER JOIN Transactions T ON
    T.transaction_date = C.calendar_date
GROUP BY
    C.calendar_date
ORDER BY
    C.calendar_date

要记住的一些事项:

如果您将其发送到前端或报告引擎,那么您应该只发送您拥有的日期(您的原始查询),如果可能的话,让前端填写$ 0.00天。

另外,我在这里假设日期是一个没有时间成分的确切日期值(因此在连接中为“=”)。您的日历表可以包含“start_time”和“end_time”,以便您可以使用BETWEEN处理包含时间部分的日期。这样可以避免必须剥离时间部分并可能破坏索引使用。您也可以在使用它时计算当天的起点和终点,但由于它是预先填充的工作表,因此IMO更容易包含start_time和end_time。

答案 1 :(得分:0)

不确定这是否适用于CE

使用公用表表达式

DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME

SET @StartDate = '2010-07-10'
SET @EndDate = '2010-07-20'

;WITH Dates AS (
    SELECT  @StartDate AS DateValue
    UNION ALL
    SELECT  DateValue + 1
    FROM    Dates
    WHERE   DateValue + 1 <= @EndDate
)
SELECT      Dates.DateValue, ISNULL(SUM(Transactions.Amount), 0)
FROM        Dates
LEFT JOIN   Transactions ON
                Dates.DateValue = Transactions.Transaction_Date
GROUP BY    Dates.DateValue;

使用循环+临时表

DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME

SET @StartDate = '2010-07-10'
SET @EndDate = '2010-07-20'

SELECT @StartDate AS DateValue INTO #Dates

WHILE @StartDate <= @EndDate
BEGIN
    SET @StartDate = @StartDate + 1
    INSERT INTO #Dates VALUES (@StartDate)
END

SELECT      Dates.DateValue, ISNULL(SUM(Transactions.Amount), 0)
FROM        #Dates AS Dates
LEFT JOIN   Transactions ON
                Dates.DateValue = Transactions.Transaction_Date
GROUP BY    Dates.DateValue;

DROP TABLE  #Dates

答案 2 :(得分:0)

你需要以某种方式限制你的陈述,但也许这会有所帮助。

DECLARE @Start  smalldatetime, @End smalldatetime

SELECT @Start = 'Jan 1 2010', @End = 'Jan 18 2010';

--- make a CTE of range of dates we're interested in
WITH Cal AS (
    SELECT CalDate = convert(datetime, @Start) 
    UNION ALL
    SELECT CalDate = dateadd(d,1,convert(datetime, CalDate))  FROM Cal WHERE CalDate < @End

)

SELECT CalDate AS TransactionDate, ISNULL(SUM(Amount),0) AS TransactionAmount
FROM  Cal AS C
LEFT JOIN Transactions AS T On C.CalDate = T.Transaction_Date
GROUP BY CalDate ;

答案 3 :(得分:0)

一旦你有了一个日历表(稍后会有更多内容),你就可以在数据范围内进行内部联接以填补缺少的日期:

SELECT CalendarDate, NULLIF(SUM(t.Amount),0)
FROM (SELECT CalendardDate FROM Calendar
WHERE CalendarDate>= (SELECT MIN(TransactionDate) FROM Transactions) AND
  CalendarDate<= (SELECT MAX(TransactionDate) FROM Transactions)) c
 LEFT JOIN 
    Transactions t ON t.TransactionDate=c.CalendarDate
GROUP BY CalendarDate

要创建日历表,您可以使用CTE:

WITH CalendarTable
AS
(
  SELECT CAST('20090601' as datetime) AS [date]
  UNION ALL
  SELECT DATEADD(dd, 1, [date])
  FROM CTE_DatesTable
  WHERE DATEADD(dd, 1, [date]) <= '20090630' /* last date */
)
SELECT [date] FROM CTE_DatesTable
OPTION (MAXRECURSION 0);

结合这两者,我们有

WITH CalendarTable
AS
(
  SELECT MIN(TransactionDate) FROM Transactions AS [date]
  UNION ALL
  SELECT DATEADD(dd, 1, [date])
  FROM CTE_DatesTable
  WHERE DATEADD(dd, 1, [date]) <= (SELECT MAX(TransactionDate) FROM Transactions) 
)
SELECT c.[date], NULLIF(SUM(t.Amount),0)
FROM Calendar c
 LEFT JOIN 
    Transactions t ON t.TransactionDate=c.[date]
GROUP BY c.[date]

答案 4 :(得分:-1)

如果您希望显示没有交易的日期 您可以为每天添加DUMMY交易,金额为零 它不会干扰SUM,你会想要什么