【问题标题】:How to create table + calculate cost involve 2 columns如何创建表+计算成本涉及2列
【发布时间】:2016-01-09 15:15:21
【问题描述】:

我想按阶段计算成本,但它不起作用我的数据如下。我正在使用这个命令来计算成本

SELECT Daily.dayno, activity.class, activity.phase,
    activity.duration/sum(activity.duration)*daily.daycost as cost
from Daily INNER JOIN
(
    Select activity.dailyuid, sum(activity.duration) duration
    group by dailyUID
) Activity
on activity.dailyuid=daily.dailyuid
group by class, phase

显然上述查询不起作用。我想要的是例如按阶段计算成本

Dailyuid DD1 中的阶段 SS1 = 4/12*1000,其中 4 是 SS1 的总小时数,12 是 dailyuid DD1 的总小时数,1000 是 dailyuid DD1 的成本。

另一个例子是阶段 ST2 = 8/12*1000 IH=10.6/11.6*2000等

每日餐桌

DailyUID | Dayno | Daycost |
---------|-------|---------|
DD1      | 1     | 1000    | 
DD2      | 2     | 2000    |
DD3      | 3     | 3000    |

活动表

DailyUID | CLASS | PHASE | Duration |
-----------------------------------
DD1      | TS    | SS1   | 3        |
DD1      | TS    | SS1   | 1        |
DD1      | TS    | ST2   | 2        |
DD1      | P     | ST2   | 6        |
DD2      | P     | IH1   | 6.6      |
DD2      | U     | IH1   | 4        |
DD2      | TS    | IH2   | 1        |
DD3      | TU    | SC1   | 7        |
DD3      | P     | SC2   | 8        |
DD3      | U     | CMPLT | 3        |

【问题讨论】:

  • 您的查询一团糟,因此我认为您应该向我们展示您的预期输出。
  • dailyUID 在两个表中不一样。是不是笔误?
  • @LelioFaieta 很抱歉我已经纠正了
  • @rookie_coder 我说的是在第一个表中你有'DD1'和第二个'DDD1'的事实。第一次是两个字母和一个数字。第二次三个字母和一个数字。这两个永远不会加入
  • @LelioFaieta 对不起,菜鸟对我来说很难,我已经纠正了他们

标签: mysql calculated-columns


【解决方案1】:

如果我理解正确,您需要在加入之前预先汇总表。需要一个额外的聚合:

select ap.phase,
       (ap.duration / ad.duration) * d.daycost as cost
from (SELECT d.dailyUid, sum(daycost) as daycost
      FROM Daily d
      GROUP BY d.dailyuid
     ) d INNER JOIN
     (Select a.dailyuid, sum(a.duration) as duration
      from activity a
      group by dailyUID
     ) ad
     on ad.dailyuid = d.dailyuid join
     (select a.dailyuid, a.phase, sum(a.duration) as duration
      from activity a
      group by a.dailyuid, a.phase
     ) ap
     on ad.dailyuid = ap.dailyuid
group by phase;

SQL Fiddle 是 here

【讨论】:

  • 您好,我在 SQL Fiddle 上试过这个,但似乎不起作用,您能否进一步建议sqlfiddle.com/#!9/1a4ae9/10
  • @rookie_coder 。 . .感谢您设置 SQL Fiddle。我已经修正了错别字。
  • 几乎是正确的,但是当我在这里使用它时,IH 计算出的值有误,其余的都是正确的,您能否建议sqlfiddle.com/#!9/cc30cc/4 该值应为 7.6/12.6*2000 = 1,206.35 但在您的查询中输出为 1230.7692提前谢谢你
  • 我调整了持续时间的值并重新运行查询,结果现在证明是正确的......非常感谢您帮助我完成这个复杂的计算
【解决方案2】:

我想我设法用SUM() OVER (...):做到了

设置:

-- drop table Daily
create table Daily
(
   DailyUID VARCHAR(6),
   DayNo INT,
   DayCost NUMERIC(18, 2)
)
go

insert into Daily values ('DD1', 1, 1000),
    ('DD2', 2     , 2000),
    ('DD1', 3     , 3000)
go

-- drop table ActivityTable
create table ActivityTable
(
    DailyUID VARCHAR(6),
    Class VARCHAR(2),
    Phase VARCHAR(6),
    Duration NUMERIC(5, 1)
)
go

insert into ActivityTable values 
('DD1'   , 'TS'    , 'SS1'   , 3        ),
('DD1'   , 'TS'    , 'SS1'   , 1        ),
('DD1'   , 'TS'    , 'ST2'   , 2        ),
('DD1'   , 'P'     , 'ST2'   , 6        ),
('DD2'   , 'P'     , 'IH1'   , 6.6      ),
('DD2'   , 'U'     , 'IH1'   , 4        ),
('DD2'   , 'TS'    , 'IH2'   , 1        ),
('DD3'   , 'TU'    , 'SC1'   , 7        ),
('DD3'   , 'P'     , 'SC2'   , 8        ),
('DD3'   , 'U'     , 'CMPLT' , 3        )
GO

脚本:(仅适用于 SQL Server,请参阅下面的 MySql 版本)

    ;WITH Sums AS (
        SELECT DISTINCT AT.DailyUID, AT.Phase, 
            SUM(AT.Duration) OVER (PARTITION BY AT.Phase, AT.DailyUID) AS PhaseDuration,
            SUM(AT.Duration) OVER (PARTITION BY AT.DailyUID) AS TotalDuration
        FROM ActivityTable AT
    )
    SELECT S.Phase, S.DailyUID, S.PhaseDuration, S.TotalDuration, S.PhaseDuration * 1.0 / S.TotalDuration * 1000
    FROM Sums S

So, grouping is done in `Sums` CTE by phase and day first and then by day only.

[编辑 - 使其适用于 MySql]

SELECT S.Phase, S.DailyUID, S.PhaseDuration, S.TotalDuration, S.PhaseDuration * 1.0 / S.TotalDuration * 1000
FROM (
    SELECT DISTINCT ATOut.DailyUID, ATOut.Phase, PD.PhaseDuration, TD.TotalDuration
    FROM ActivityTable ATOut
        JOIN (SELECT AT.Phase, AT.DailyUID, SUM(AT.Duration) PhaseDuration FROM ActivityTable AT GROUP BY Phase, DailyUID) PD 
            ON PD.Phase = ATOut.Phase AND PD.DailyUID = ATOut.DailyUID
        JOIN (SELECT AT.DailyUID, SUM(AT.Duration) TotalDuration FROM ActivityTable AT GROUP BY DailyUID) TD 
            ON TD.DailyUID = ATOut.DailyUID
) S

【讨论】:

  • 对不起,我错过了。我还包括了一个 MySQL 版本,虽然你的工作正常。可惜 MySql 缺少 T-SQL 的这么多特性。
  • 。 .这些功能不是来自 T-SQL。它们是 ANSI 标准功能。而且,是的,当数据库不支持有用的 ANSI 构造时,这是一种耻辱。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-02
  • 1970-01-01
  • 1970-01-01
  • 2017-04-07
  • 1970-01-01
相关资源
最近更新 更多