帮我完成这个 SQL 查询

发布于 2024-09-11 11:47:17 字数 401 浏览 1 评论 0原文

我有一个 SQL Server CE 3.5 表(事务),具有以下架构:

  • ID
  • Transaction_Date
  • 类别
  • 描述
  • 金额

查询:

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

我正在尝试执行 SUM(金额)并按 transaction_date 进行分组,以便我可以获取每天的总金额,但即使没有交易的日子我也想取回值,所以基本上没有交易的一天的记录只有 0.00 美元的金额。

感谢您的帮助!

I've got a SQL Server CE 3.5 table (Transactions) with the following Schema:

  • ID
  • Transaction_Date
  • Category
  • Description
  • Amount

Query:

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

I'm trying to do a SUM(Amount) and group by transaction_date just so I can get the total amount for each day but I want to get back values even for days there were no transactions so basically the record for a day with no transactions would just have $0.00 for amount.

Thanks for the help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

情愿 2024-09-18 11:47:17

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

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 来处理包含时间部分的日期。这使您不必削减时间部分并可能破坏索引的使用。您也可以在使用它时计算一天的开始和结束点,但由于它是一个预填充的工作表,因此在我看来更容易包含开始时间和结束时间。

You need a Calendar table to select over the dates. Alternatively, if you have a Numbers table, you could turn that effectively into a Calendar table. Basically, it's just a table with every date in it. It's easy enough to build and generate the data for it and it comes in very handy for these situations. Then you would simply use:

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

A few things to keep in mind:

If you're sending this to a front-end or reporting engine then you should just send the dates that you have (your original query) and have the front end fill in the $0.00 days itself if that's possible.

Also, I've assumed here that the date is an exact date value with no time component (hence the "=" in the join). Your calendar table could include a "start_time" and "end_time" so that you can use BETWEEN for working with dates that include a time portion. That saves you from having to strip off time portions and potentially ruining index usage. You could also just calculate the start and end points of the day when you use it, but since it's a prefilled work table it's easier IMO to include a start_time and end_time.

节枝 2024-09-18 11:47:17

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

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 ;

You'll need to upper and lower bound your statement somehow, but perhaps this will help.

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 ;
[旋木] 2024-09-18 11:47:17

一旦您有了日历表(稍后会详细介绍),您就可以对数据范围进行内部联接以填充缺失的日期:

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]

Once you have a Calendar table (more on that later) you can then do an inner join on the range of your data to fill in missing dates:

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

To create a calendar table, you can use a 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);

Combining the two, we have

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]
向日葵 2024-09-18 11:47:17

不确定这是否适用于 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

Not sure if any this works with CE

With common table expressions

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;

With loop + temporary table

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
何以心动 2024-09-18 11:47:17

如果您希望显示没有交易的日期
您可以每天添加一笔金额为零的虚拟交易
它不会干扰 SUM 并且会是你想要的

If you want dates that don't have transactions to appear
you can add a DUMMY transaction for each day with the amount of zero
it won't interfere with SUM and would so what you want

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文