mysql INNER JOIN不像我想的那样工作

时间:2012-11-11 03:18:26

标签: mysql

有两张桌子:

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
;

这是对所有列的总结。

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

由于

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分: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

第一阶段是表的连接,以生成要考虑的所有行的列表。因此,在上面的简化示例中,我们正在查看在fk_cusip6上的issue_details和标识符匹配之间的连接。此阶段生成一个包含四行的列表(每个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()的聚合,所以我们进入第二阶段。

第二阶段确定应将哪些行拼凑在一起以执行聚合。我说bucketed,但在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,因此查询处理器会将第一阶段的行分配到每个identifier.id值的独立存储桶中。所以我们得到这样的东西:

+ ------- + ----- + + -------------- ------------ + ---- ------------ + --------- + ----------------- +    |斗| id |成熟度| fk_cusip6 | amt_offer_dlr | ide.id | iden.fk_cusip6 |    | ------- + ----- + -------------- + ------------ + ------- --------- --------- + + + -----------------    | A | 1 | 2013-06-28 | 567090 | 1000 | 131472 | 567090 |    | A | 2 | 2014-06-05 | 567090 | 1000 | 131472 | 567090 |    | ------- + ----- + -------------- + ------------ + ------- --------- --------- + + + -----------------    | B | 3 | 2013-06-05 | 567100 | 2500 | 131473 | 567100 |    | B | 3 | 2014-06-05 | 567100 | 2500 | 131473 | 567100 |    + ------- + ----- + -------------- + ------------ + ------- --------- + --------- + ------------------- +

(抱歉,我无法弄清楚如何格式化这个表格)

Bucket A是所有行,其标识符为.id = 131472,而存储桶B的标识符为.id = 131473。

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

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

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