【问题标题】:One select sum, the same one minus another sum inside a single query一个选择总和,相同的一个减去单个查询中的另一个总和
【发布时间】:2013-07-26 19:04:10
【问题描述】:

我有这三个表:

  • 帐号:id(pk)、value、ug(fk)、flag
  • 证明:id(pk)、value、account_id(fk)
  • 客户端:id(pk), ug(fk)

我有这两个选择:

select sum(account.value)
  from account, client
 where client.ug_id = account.ug and flag = 1

select sum(justify.value)
  from justify, client, account
 where client.ug_id = account.ug
   and flag = 1 and justify.account_id = account.id

我正在尝试将它们放在一个查询中,如下所示:

select
1,
1-2,
account.ug
from account
group by account.ug

但我找不到办法;有什么想法吗?

【问题讨论】:

  • 您能否添加有关表格及其数据的更好信息,这会有所帮助。此外,如果您使用联接而不是从各种表中选择,则查询将执行得更好,谢谢
  • 欢迎来到 Stack Overflow。请尽快阅读About 页面。 FROM 子句中的表 lit 和 JOIN 列表之间不应该有任何性能差异,但后者通常更容易理解。没有 GROUP BY 子句;这是你真正想要的——每个查询中的一个数字吗?您的组合查询包括 GROUP BY,因此不清楚它是否与前两个有很大关系。

标签: sql select sum


【解决方案1】:

您并没有真正告诉我们有关您的架构的太多信息。但是(试一试)……

首先,您应该使用 ANSI/ISO 连接,而不是老式连接。 ANSI/ISO 连接更容易阅读。一旦你这样做了,你就会想要使用派生表,它们是from 子句中充当虚拟视图的子查询。那么,你应该这样做:

select ug    = account.ug , -- guaranteed to be present ,
       total = coalesce( total.value   , 0 ) ,
       delta = coalesce( total.value   , 0 ) ,
             - coalesce( justify.value , 0 )
from      ( select distinct -- we do select distinct here
                   ug       -- to guarantee at least one row for every UG
            from account    -- some account UGs might be missing client rows
          ) account         -- and/or some might be missing justify rows.
left join ( select ug    = account.ug ,
                   value = sum(account.value)
            from account
            join client  on client.ug_id = account.ug
            where flag = 1
            group by account.ug
          ) total on total.ug = account.ug
left join ( select ug    = account.ug ,
                   value = sum(justify.value)
            from account
            join justify on justify.account_id = account.id
            join client  on client.ug_id       = account.ug
            where flag = 1
            group by account.ug
          ) justify on justify.ug = account.ug

【讨论】:

  • 哪个 DBMS 使用 'alias = real-value' 表示法? SQL 标准将是“实值 AS 别名”。没有错,但很不寻常。
  • SQL Server、DB2 等。从 DB2 第 1 版开始,这种约定就一直存在。Oracle 不支持它,但 Oracle 是目前最不标准的 RDBMS。 AS 的问题在于,在选择列表中有很多派生列和复杂表达式的复杂 SELECTS 中,派生列名称的名称在随机播放中会变得很多。使用 name=expression 使选择更具可读性。
【解决方案2】:

我们真的不应该对你的问题做任何猜测,但似乎猜测是必要的。

我认为你的三张桌子是:

  1. Account — id (PK)、value、ug(FK 引用客户端)、flag
  2. 客户 — ug (PK)
  3. Justify — 值,account_id(PK,也 FK 引用 Account)

我假设没有客户就没有帐户,没有帐户就没有理由条目(因此 PK 和 FK 约束都由 DBMS 强制执行)。这意味着不必从 Client 表中进行选择。

如果您希望客户不一定也列出任何帐户,您可能最好单独查询,但如有必要也可以这样做 - 您必须澄清您的问题,并使用额外的级别外连接,并担心空值与零等。

看来需要的输出是:

  • 对于每个客户,列出客户标识符 (ug)、帐户表 (account.value) 中其帐户值的总和,以及其帐户值减去表中值的总和对齐表。尚不清楚每个帐户的 Justify 表中是否总是存在值。

但是,我们可以尝试通过逐步构建查询来提供信息。

为特定用户汇总帐户值

SELECT a.ug, SUM(a.value) AS ac_value
  FROM Account AS a
 WHERE a.flag = 1
 GROUP BY a.ug

为特定用户聚合 Justify 的值

SELECT a.ug, SUM(j.value) AS ju_value
  FROM Account AS a
  JOIN Justify AS j ON j.account_id = a.id
 WHERE a.flag = 1
 GROUP BY a.ug

前两个结果表的连接

SELECT b.ug, b.ac_value, b.ac_value - NVL(d.ju_value, 0) AS delta
  FROM (SELECT a.ug, SUM(a.value) AS ac_value
          FROM Account AS a
         WHERE a.flag = 1
         GROUP BY a.ug
       ) AS b
  LEFT JOIN
       (SELECT a.ug, SUM(j.value) AS ju_value
          FROM Account AS a
          JOIN Justify AS j ON j.account_id = a.id
         WHERE a.flag = 1
         GROUP BY a.ug
       ) AS d ON b.ug = d.ug

NVL 的使用允许客户端在 Justify 表中没有条目; LEFT JOIN 也是其中的一部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-02
    • 2016-05-15
    • 2013-05-31
    • 2022-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多