【问题标题】:SQL using CASE STATEMENT - compute for sum of amount based on the existence of it in another tableSQL 使用 CASE STATEMENT - 根据它在另一个表中的存在来计算金额的总和
【发布时间】:2014-12-19 23:12:09
【问题描述】:

更新

我正在为不同地点的购物中心租户开发一个在线销售监控系统,使用我只是升级和修改的现有系统。所有销售交易都将被汇总,包括默认的折扣,只有在折扣被批准时才将折扣排除在销售总和中。我的问题将集中在该交易上 - 考虑到每个给定日期和每个租户的折扣金额的排除和包含,获得正确的总销售额。

这是现有数据库结构的预览供您参考。

场景/示例:

我想获得 Location1 与 2 个租户在 2014 年 1 月的销售报告,1 月 1 日和 3 日 的 CMJOLL13(租户1)折扣已获批准, 1 月 1 日和 2 日的 CMMISL13(租户 2)折扣已获批准。

我应该得到那个地点的月度总销售额报告,列出 2 个租户的总销售额,考虑到折扣扣除和包含。

Daily Table 

   Tenantcode   Date        Other   Cash     Charge     Gift      GrossSales 
                                                                  (Formulated column)

   CMJOLL13     01/01/2014  100     100      100        100       300
   CMJOLL13     01/02/2014  100     100      100        100       400
   CMJOLL13     01/03/2014  100     100      100        100       300
                and so on
   CMMISL13     01/01/2014  100     100      100        100       300
   CMMISL13     01/02/2014  100     100      100        100       300
   CMMISL13     01/03/2014  100     100      100        100       400
                and so on



Discount Table

            Date        Tenantcode

            01/01/2014  CMJOLL13
            01/03/2014  CMJOLL13
            01/01/2014  CMMISL13
            01/02/2014  CMMISL13

期望/正确的输出

Monthly Table (Jan 2014) - will display the summation amount based on the example only

     Tenantcode   GrossSales
     CMMISL13     1000
     CMJOLL13     1000

这是我目前拥有的代码

select a.tenantcode,  convert(varchar(10), a.date, 101) as Date,  
        SUM(a.other)  as Other, SUM(a.CASH) as Cash,
        SUM(a.CHARGE) AS Charge, SUM(a.GIFT) AS Gift,

        case 

        when a.date IN (select  Z.date from discount Z inner join daily a on z.date = a.date and z.tenantcode = a.tenantcode where Z.date between '01/01/2014' and '01/31/2014' and a.location = 1)

        THEN (SUM(a.cash) + SUM(a.charge) + SUM(a.gift))

        ELSE (SUM(a.cash) + SUM(a.charge) + SUM(a.gift) + SUM(a.other))

        END as GrossSales

        into #MonthlyTemp

        from  TENANT b inner join LOCATION c on b.location=c.location inner join DAILY a on a.tenantcode=b.tenantcode

        where a.location = 1  AND 
            a.date  BETWEEN  '02/01/2014' and '02/28/2014'

        GROUP BY a.tenantcode , a.date 




    SELECT tenantcode, SUM(GrossSales)
        from #MonthlyTemp
        where LOCATION = 1   AND
        date  BETWEEN  '01/01/2014' and '01/31/2014'
        group by  tenantcode

基于查询的实际输出

         Tenantcode   GrossSales
         CMMISL13     900
         CMJOLL13     900

显然它不会返回正确的期望输出。 我认为这是因为万一部分的日期显示折扣表中的所有日期。我在上面的代码中使用了临时表,现在我正在考虑在 sql 中使用 While 循环来测试每个位置。

任何帮助将不胜感激。希望得到您的专业建议。祝您有美好的一天!

【问题讨论】:

  • 合并销售额不应该是300+400+400 = 1100吗?
  • 是的!我站得更正了。谢谢你:)我真的被这个问题困住了。
  • 你为什么要拿SUM的东西?同一天的租户代码可以有多个折扣吗?
  • 因为一个租户代码可能有超过 1 个终端号,并且它是我没有包含的列的一部分,以便更短的展示。每个租户代码应总结其结合所有终端的所有销售额。日常销售实际上没有问题,因为我能够实现所需的输出,我的问题是在不是每天的情况下使用 CONSOLIDATED,但是给定一个日期范围,比如说每周或每月
  • 回答,是的,可能有两个或多个终端没有列都具有相同的租户代码

标签: sql sql-server subquery case exists


【解决方案1】:

您可以使用此查询来更新 Daily 表中的 GrossSales 列。

UPDATE A
SET GrossSales = A.Cash + A.Charge + A.Gift + CASE WHEN A.TenantCode IS NOT NULL THEN A.Other ELSE 0
FROM Daily A LEFT JOIN Discount B on A.Date = B.Date and A.TenantCode = B.TenantCode

编辑:

如果 GrossSales 不是真正的列,则可以使用临时表。

select *, 0 GrossSales
INTO #Daily
FROM Daily

UPDATE A
SET GrossSales = A.Cash + A.Charge + A.Gift + CASE WHEN A.TenantCode IS NOT NULL THEN A.Other ELSE 0
FROM #Daily A LEFT JOIN Discount B on A.Date = B.Date and A.TenantCode = B.TenantCode

UPDATE A
SET A.GrossSales = B.GrossSales
FROM Consolidated A JOIN (SELECT TenantCode, SUM(GrossSales) FROM #Daily GROUP BY TenantCode) B 
ON A.TenantCode = B.TenantCode

【讨论】:

  • 我忘了强调总销售额不是每日表中的预定义列。它只是使用一个函数来制定的,所以这是不可能的,也是难以实现我想要的输出的原因之一。
  • 我会试试你的解决方案,非常感谢!只有几个问题,使用临时表来实现我想要的输出是理想的吗?我的意思是性能方面。没有使用临时表而是通过普通查询、子查询等的解决方案吗?
  • 临时表的性能通常比子查询好。它还提供了子查询没有的可重用性。其他选项也是使用表变量。
  • 那很好,水晶报表中也可以通过sql命令读取吗?
  • 很抱歉造成混淆,但没有合并表。它也是定制的,我是否也应该为它创建一个临时表?基于哪一列?
【解决方案2】:
select a.tenantcode,  convert(varchar(10), a.date, 101) as Date,  
SUM(a.other)  as Other, 
SUM(a.CASH) as Cash,
SUM(a.CHARGE) AS Charge,
SUM(a.GIFT) AS Gift,

case 

when a.date IN (select b.date from discount b  where b.date between '02/01/2014' and '02/28/2014' and b.tenantcode = 'CMMISL13')
THEN (SUM(a.cash) + SUM(a.charge) + SUM(a.gift))

ELSE ((SUM(a.cash) + SUM(a.charge) + SUM(a.gift) + SUM(a.other)) - SUM(a.surcharge))
END as GrossSales

into #NewDailyTemp //Include it to create a temp table

from  TENANT b inner join LOCATION c on b.location=c.location inner join DAILY a on a.tenantcode=b.tenantcode

where b.tenantcode = 'CMMISL13'  AND 
    a.date  BETWEEN  '02/01/2014' and '02/28/2014'


GROUP BY a.tenantcode , a.date 

然后

SELECT tenantcode, SUM(GrossSales) 
    from #NewDailyTemp
    where tenantcode = 'CMMISL13'  AND 
    date  BETWEEN  '02/01/2014' and '02/28/2014'
    group by tenantcode 

达到了预期的输出。将其集成到 ASP.NET 编程和水晶报表中是另一个主题

【讨论】:

  • 但它仍然不是单行 sql 查询,这在某种程度上令人沮丧,虽然 OUTPUT-WISE,没关系,也许真的不可能对我想要的输出进行单行查询。 ??
  • 这个答案对每个租户来说都是正确的,但是为了达到 ALL TENANT ,它没有给出正确的答案,为了清楚起见,我会更新我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多