0

有两张桌子:

CREATE  TABLE IF NOT EXISTS `issue_details` (
    `id` INT NOT NULL AUTO_INCREMENT ,
    amt_offer_dlr INT NOT NULL DEFAULT 9999 COMMENT '564,510,000',
   maturity  DATE NOT NULL DEFAULT '1111-11-11' COMMENT '06/28/2012' ,
    fk_cusip6 VARCHAR(6) NOT NULL DEFAULT '' COMMENT '' ,
  PRIMARY KEY (id),
  CONSTRAINT con_issue_details__issuers FOREIGN KEY (fk_cusip6) REFERENCES issuers    (fk_cusip6) ON DELETE NO ACTION ON UPDATE CASCADE
)
ENGINE = InnoDB;

CREATE  TABLE IF NOT EXISTS `identifiers` (
  id     INT NOT NULL AUTO_INCREMENT ,
  fk_cusip6 VARCHAR(6)  NOT NULL DEFAULT 'NA' ,
  PRIMARY KEY (id) ,
  CONSTRAINT con_ident__cusip6  FOREIGN KEY (fk_cusip6) REFERENCES cusip_6 (cusip6) ON DELETE NO ACTION ON UPDATE CASCADE ,
)
COMMENT ''
 ENGINE = InnoDB;

issue_details 表:注意:每个 id 不同可以有多个相同的 fk_cusip6 数字

+-----+--------------+------------+----------------+
| id  | maturity     | fk_cusip6  |  amt_offer_dlr |
+-----+--------------+------------+----------------+
|  1  | 2013-06-28   | 567090     |  1000          |
|  2  | 2014-06-05   | 567090     |  1000          |
|  3  | 2013-06-05   | 567100     |  2500          |
|  3  | 2014-06-05   | 567100     |  2500          |
+-----+--------------+------------+----------------+

标识符表:注意:每个 fk_cusip6 编号不同

+--------+-----------+
| id     | fk_cusip6 |
+--------+-----------+
| 131472 | 567090    |
| 131473 | 567100    |
+--------+-----------+

我需要生成一个查询,该查询将匹配标识符表中 fk_cusip6 的每个实例,然后对 issue_details 表中具有相同 fk_cusip6 的所有实例求和 amt_offer_dlr。最终结果应该是:

+--------------+---------+------------------------+
| ide.id | isd.fk_cusip6 |  SUM(isd.Amt_Offer_Dlr |
+--------------+---------+------------------------+
| 131472 | 567090        | 2000                   |
| 131473 | 567100        | 5000                   |
+--------------+---------+------------------------+

我试过:

SELECT CURRENT_DATE, FORMAT(SUM(isd.Amt_Offer_Dlr),0) 'Current Out Standing Debt:'
from muni.issue_details isd
INNER JOIN identifiers ide ON ide.fk_cusip6 = isd.fk_cusip6 AND  isd.fk_cusip6 = '567541'
where isd.maturity > CURRENT_DATE
;

这是对所有列的总和。

我想我需要一个子查询,但我坚持细节。

谢谢

4

2 回答 2

2

试试这个:

SELECT
    i.id,
    i.fk_cusip6,
    x.amt_offer_dlr_sum

FROM identifiers i

INNER JOIN (
    SELECT
        id.fk_cusip6,
        SUM(id.amt_offer_dlr) AS amt_offer_dlr_sum
    FROM issue_details id
    GROUP BY id.fk_cusip6
) x
ON x.fk_cusip6 = i.fk_cusip6;
于 2012-11-11T03:21:58.630 回答
2

将 SQL 中的查询过程视为一个三阶段活动。这可能无法捕捉到实际发生的所有丰富性,但在您的情况下它在逻辑上是准确的。

让我们简化查询以删除日期/成熟度检查并检查单个 fk_cusip6 值,因此它只是:

SELECT SUM(isd.Amt_Offer_Dlr) 
FROM muni.issue_details isd
INNER JOIN identifiers ide ON ide.fk_cusip6 = isd.fk_cusip6

第一阶段是表的连接,以生成要考虑的所有行的列表。因此,在上面的简化示例中,我们正在查看 issue_details 和 fk_cusip6 上匹配的标识符之间的连接。此阶段生成一个包含四行的列表(每个 issue_details 行一个,并附加相应的标识符行)。

这给了你一个这样的结构:

+-----+--------------+------------+----------------+---------+----------------+
| id  | maturity     | fk_cusip6  |  amt_offer_dlr | ide.id  | ide.fk_cusip6  |
+-----+--------------+------------+----------------+---------+----------------+
|  1  | 2013-06-28   | 567090     |  1000          |  131472 |  567090        |
|  2  | 2014-06-05   | 567090     |  1000          |  131472 |  567090        |
|  3  | 2013-06-05   | 567100     |  2500          |  131473 |  567100        |
|  3  | 2014-06-05   | 567100     |  2500          |  131473 |  567100        |
+-----+--------------+------------+----------------+---------+----------------+

现在,一个像这样的非聚合 SQL 语句:

SELECT *
FROM muni.issue_details isd
INNER JOIN identifiers ide ON ide.fk_cusip6 = isd.fk_cusip6

只会返回那张桌子。但是你有一个与 SUM() 的聚合,所以我们进入第二阶段。

第二阶段确定哪些行应该被存储在一起以执行聚合。我说的是分桶,但在 SQL 术语中,我们会说哪些行被分组在一起,这意味着可能使用 GROUP BY 子句。但是,在我们的查询中,没有 GROUP BY 子句,因此查询处理器必须选择将所有行分组到一个存储桶中。这不是您想要的,但没有任何关于如何对行进行分组的说明,这是处理器必须做的。因此,您的聚合将对所有四行执行一次聚合。

第三阶段是实际的聚合本身。这是我们总结所有四行结果的地方。在上面的示例查询中,我们只会看到 1000+1000+2500+2500 或 7000 的输出。同样,这不是您想要的。

现在考虑这个替代查询:

SELECT ide.id, isd.fk_cusip6, SUM(isd.Amt_Offer_Dlr) 
FROM muni.issue_details isd
INNER JOIN identifiers ide ON ide.fk_cusip6 = isd.fk_cusip6
GROUP BY ide.id, isd.fk_cusip6

此查询的第一阶段与之前相同;作为内部连接的结果,生成了四行。

但是,在第二阶段,现在我们有一个 GROUP BY,因此查询处理器会将第一阶段的行分桶到每个 identifiers.id 值的单独桶中。所以我们得到这样的东西:

+--------+-----+--------------+------------+------- ---------+---------+-----------------+ |桶 | 编号 | 成熟度 | fk_cusip6 | amt_offer_dlr | ide.id | iden.fk_cusip6 | |--------+-----+--------------+------------+------- ---------+---------+-----------------+ | 一个 | 1 | 2013-06-28 | 567090 | 1000 | 131472 | 567090 | | 一个 | 2 | 2014-06-05 | 567090 | 1000 | 131472 | 567090 | |--------+-----+--------------+------------+------- ---------+---------+-----------------+ | 乙| 3 | 2013-06-05 | 567100 | 2500 | 131473 | 567100 | | 乙| 3 | 2014-06-05 | 567100 | 2500 | 131473 | 567100 | +--------+-----+--------------+------------+------- ---------+---------+------------------+

(对不起,我不知道如何格式化这么宽的表格)

Bucket A 是 identifiers.id=131472 的所有行,bucket B 是 identifiers.id=131473 的所有行。

第三阶段为每个存储桶执行聚合,为您提供所需的结果:

+--------------+---------+------------------------+
| ide.id | isd.fk_cusip6 |  SUM(isd.Amt_Offer_Dlr |
+--------------+---------+------------------------+
| 131472 | 567090        | 2000                   |
| 131473 | 567100        | 5000                   |
+--------------+---------+------------------------+

只要您要应用的其他搜索条件简单明了,我认为您不需要子查询。但即便如此,如果条件变得更复杂,您必须弄清楚它们是否进入子查询、连接子句或整个 WHERE 子句本身,这可能会导致混淆。我尽量保持选择尽可能简单。

于 2012-11-11T03:46:52.997 回答