【问题标题】:Get daily sales for every day this month获取本月每一天的每日销售额
【发布时间】:2016-02-15 02:03:51
【问题描述】:

我有一个查询,获取当天的总销售额

SELECT 
    SUM(cso.SubTotal) - (
        SELECT SUM(cso.CreditAvailable) / 1.1 
        FROM dbo.CustomerCredit cso 
        WHERE CONVERT(VARCHAR(10), cso.DateCreated, 102) = CONVERT(VARCHAR(10), SYSDATETIME(), 102)
    ) AS total_value 
FROM dbo.CustomerInvoice cso 
WHERE
    Convert(VARCHAR(10), cso.InvoiceDate, 102) = Convert(VARCHAR(10), SYSDATETIME(), 102) 

我现在需要的是一个表格,其中左侧列是当月所有日期的列表,右侧列是每个日期的总销售额(使用上面的查询)

+---------+---------+
|  date   |  total  |
+---------+---------+
| 1/2/16  | 256232  |
| 2/2/16  | 285632  |
| 3/2/16  | 265231  |
| 4/2/16  | 254215  |
| 5/2/16  |    0    |
| ....... |  .....  |
| 28/2/16 |    0    |
| 29/2/16 |    0    |
+-------------------+

对于未来发生的日期或周末日期的销售价值是否为零并不重要。

我绞尽脑汁想找到一个解决方案,但由于我只是 SQL 新手,所以我决定接触社区。​​p>

【问题讨论】:

  • 我通常使用Calendar table
  • 和;当然,30/2 和 31/2 永远不会存在

标签: sql sql-server sql-server-2008


【解决方案1】:

你可以像这样使用查询:

;with date_cur_month as(
select convert(datetime, convert(varchar(6), getdate(), 112) + '01', 112) as dt
union all
select dateadd(day, 1, dt) as dt
  from date_cur_month
  where datepart(month, dateadd(day, 1, dt)) = datepart(month, getdate()))

select convert(nvarchar(8), d.dt, 3) as date
     , isnull(sum(ci.SubTotal), 0) 
     - isnull((select sum(cc.CreditAvailable) / 1.1 
                 from dbo.CustomerCredit cc
                 where cast(cc.DateCreated as date) = d.dt
              ), 0) as total 
  from dbo.CustomerInvoice ci 
    right outer join date_cur_month d on cast(ci.InvoiceDate as date) = d.dt
  group by d.dt

【讨论】:

  • 谢谢!!效果很好......我如何获得每天的累计销售额?所以 Sales_Day2 = (Sales_Day1) + (Sales_Day2) ??
  • 对于每天的累计销售额,您可以将
  • 您需要将 "cast(cc.DateCreated as date) = d.dt" 替换为 "cast(cc.DateCreated as date)
  • 谢谢!只是一个问题,我怎样才能让“日期”列以 dd/mm/yyyy 格式显示??
  • 将“convert(nvarchar(8), d.dt, 3)”替换为“convert(nvarchar(10), d.dt, 103)”。
【解决方案2】:

首先,我相信您的查询可以写成:

SELECT
    SUM(SubTotal) - (SUM(CreditAvailable) / 1.1) AS total
FROM dbo.CustomerInvoice
WHERE CAST(InvoiceDate AS DATE) = CAST(SYSDATETIME() AS DATE)

要获取每个日期的总数,只需添加GROUP BY

SELECT
    SUM(SubTotal) - (SUM(CreditAvailable) / 1.1) AS total
FROM dbo.CustomerInvoice
GROUP BY CAST(InvoiceDate AS DATE)

现在,要包含所有日期,即使是总数为 0 的日期,您必须使用 tally table

DECLARE @fromDate AS DATE   = '20160101',
        @toDate AS DATE     = '20160131'

;WITH E1(N) AS(
    SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b),
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b), 
CteTally(N) AS(
    SELECT TOP(DATEDIFF(DAY, @fromDate, @toDate) + 1) ROW_NUMBER() OVER(ORDER BY(SELECT NULL))
    FROM E4
),
CteDates(dt) AS(
    SELECT DATEADD(DAY, N - 1, @fromDate) FROM CteTally
)
SELECT
    d.dt, t.total
FROM CteDates d
LEFT JOIN (
    SELECT
        dt = CAST(InvoiceDate AS DATE),
        total = SUM(SubTotal) - (SUM(CreditAvailable) / 1.1)
    FROM dbo.CustomerInvoice
    WHERE InvoiceDate >= @fromDate AND InvoiceDate < DATEADD(DAY, 1, @toDate)
    GROUP BY CAST(InvoiceDate AS DATE)
) t
    ON t.dt = d.dt

【讨论】:

  • 谢谢菲利克斯!我认为这会起作用,除了您错过了“CreditAvailable”在表 dbo.CustomerCredit 上的事实。其余的都在 dbo.CustomerInvoice 上。我已重新格式化以显示 dt = CAST(InvoiceDate AS DATE), SUM(SubTotal) - (SELECT SUM(CreditAvailable) / 1.1 FROM dbo.CustomerCredit WHERE DateCreated >= @fromDate AND DateCreated
  • 完全错过了那部分。无论如何,您可以编辑此答案。
  • 这根本没有给我正确的数字菲利克斯... :(
【解决方案3】:
WITH cteRange
AS (SELECT
        DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) AS Start_Date
    UNION ALL
    SELECT
        DATEADD(DAY, 1, cteRange.Start_Date)
    FROM cteRange
    WHERE cteRange.Start_Date < DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) + 1, 0))
    )
SELECT
    cteRange.Start_Date, ISNULL(inv.SubTotal,0), ISNULL(crd.CredAvail,0)
  , ISNULL(inv.SubTotal,0) - ISNULL(crd.CredAvail / 1.1,0) AS total
FROM cteRange
LEFT JOIN (SELECT
            CAST(cc.DateCreated AS date) AS DateCreated
          , SUM(cc.CreditAvailable) AS CredAvail
        FROM dbo.CustomerCredit AS cc
        WHERE cc.DateCreated >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
        GROUP BY CAST(cc.DateCreated AS date)
        ) AS crd ON cteRange.Start_Date = crd.DateCreated
LEFT JOIN (SELECT
            CAST(cso.InvoiceDate AS date) AS InvoiceDate
          , SUM(cso.SubTotal) As SubTotal
        FROM dbo.CustomerInvoice AS cso
        WHERE cso.InvoiceDate >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
        GROUP BY CAST(cso.InvoiceDate AS date)
        ) AS inv ON cteRange.Start_Date = inv.InvoiceDate
;

此计算返回当月的第一天:DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) 然后“递归公用表表达式”(CTE) 将当月所有有效天的日期添加到该日期。所以我们最终得到了该月的一组行。然后我们对您的财务数据使用左连接。

对于所涉及的 2 个表中的每一个,我们都会汇总当前月份中允许连接发生的所有数据。

请注意,为了从日期/时间信息中获得最佳性能,您应该尽量避免将它们转换为 varchars。

【讨论】:

  • 谢谢,刚刚在“GROUP BY CAST(cc.DateCreated AS date)”之后收到“AS 附近语法不正确”的错误??
  • 抱歉,我在 ISNULL() 引用中有太多右括号,现在有一个新行以 , ISNULL( 开始,更正位于计算的第二部分 ISNULL(crd.CredAvail / 1.1,0) AS total 中,这是错误的ISNULL(crd.CredAvail / 1.1),0)[那个1.1后面的括号是错的]
  • 顺便说一下,这不是为累积值设置的,问题中并不清楚
  • 谢谢...有什么办法可以隐藏中间的两列?我真的只需要计算总数...
  • 当然,只需将它们从 select 子句中删除即可。如果你不尝试它,你将不会学习。 NB。逗号分隔 select 子句中列出的列。您需要更改的是具有 isnull 引用的 select 子句
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-13
  • 1970-01-01
  • 1970-01-01
  • 2018-08-12
  • 2021-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多