【问题标题】:Combine 2 SQL Queries into 1 Using results from the First使用第一个的结果将 2 个 SQL 查询合并为 1 个
【发布时间】:2017-08-30 19:33:20
【问题描述】:

我是 SQL 和 PLSQL 的新手。我在想有一种方法可以加入这两个查询,但我很难过。它们完全相同,除了第一个查询找到一个不同的 e.identifying_party,比如“5111”,然后第二个查询使用 e.identifying_party = “5111”找到一个不同的 child_id。

SELECT DISTINCT e.identifying_party
FROM voucher b,
  cc_authorization d,
  case e,
      episode g,
      invoice c,
      invoice_item f,
      svcperiod_info v
    WHERE b.cc_authorization_id = d.cc_authorization_id
    AND d.subsidy_id            = g.episode_id
    AND g.case_id               = e.case_id
    AND b.voucher_id            = f.voucher_id
    AND f.invoice_id            = c.invoice_id
    AND v.svcperiod_id          = c.svcperiod_id
    AND f.status                = 8
    AND f.net_amount            > 0
    AND (v.end_dt              >= '01-APR-17'
    AND v.end_dt                < '02-APR-17')
    AND e.case_id               <4000; 

第二个查询完全相同,但使用 e.identifying_party 的输入:

SELECT DISTINCT b.child_id
FROM voucher b,
  cc_authorization d,
  case e,
      episode g,
      invoice c,
      invoice_item f,
      svcperiod_info v
    WHERE b.cc_authorization_id = d.cc_authorization_id
    AND d.subsidy_id            = g.episode_id
    AND g.case_id               = e.case_id
    AND b.voucher_id            = f.voucher_id
    AND f.invoice_id            = c.invoice_id
    AND v.svcperiod_id          = c.svcperiod_id
    AND f.status                = 8
    AND f.net_amount            > 0
    AND (v.end_dt              >= '01-APR-17'
    AND v.end_dt                < '02-APR-17')
    AND e.identifying_party     = 5111
    AND e.case_id               <4000;

另外,我正在调试别人的代码,所以如果有任何其他编辑或缺失信息,请告诉我。谢谢!

【问题讨论】:

  • 从不from 子句中使用逗号。 始终使用正确、明确的join 语法。
  • 您不应再使用 1980 年代的这种连接语法。出于某种原因,在 1992 年引入了显式连接。不要将日期与字符串进行比较。尤其是那些包含您希望 DBMS 正确理解和解释的某种语言的日期名称的文件。立即使用日期文字:AND (v.end_dt &gt;= DATE '2017-04-01' AND v.end_dt &lt; '2017-04-02'。不要使用混淆别名。 c 与发票有什么关系?使用iinv 或其他我们可以阅读和理解的内容。
  • 你是什么意思加入?你希望你的结果如何?如果您在第一个查询中使用 Select distinct e.identifying_party, b.child_id,您还将获得 child_id,它的 identify_party = 5111 这是您第二个查询的条件。
  • 嗨!只是想说我注意到您有一个名为“case”的表,这是 SQL 中的保留字(至少是 Oracle 和 Mssql)。这可能会导致不可预测的行为,最好避免。
  • 感谢@ThorstenKettner 的编辑!

标签: sql oracle


【解决方案1】:

由于除了您要提取的特定字段之外,查询是相同的,因此从逻辑上讲,查询会返回您需要的所有数据 - 您只需要询问即可:

SELECT DISTINCT e.identifying_party, b.child_id
  FROM voucher b
  INNER JOIN cc_authorization d
    ON d.cc_authorization_id = b.cc_authorization_id
  INNER JOIN episode g
    ON g.subsidy_id = d.episode_id
  INNER JOIN case e
    ON e.case_id = g.case_id
  INNER JOIN invoice_item f
    ON f.voucher_id = b.voucher_id
  INNER JOIN invoice c
    ON c.invoice_id = f.invoice_id
  INNER JOIN svcperiod_info v
    ON v.svcperiod_id = c.svcperiod_id
  WHERE f.status     = 8 AND
        f.net_amount > 0 AND
        v.end_dt    >= '01-APR-17' AND
        v.end_dt    <  '02-APR-17' AND
        e.case_id   <  4000
  ORDER BY IDENTIFYING_PARTY, CHILD_ID

在这里,我重写了查询以使用“现代”连接(SQL-92 - 25 年“新” - 我的,时间过得真快 :-) 但原始查询应该可以正常工作。

这将为您提供 IDENTIFYING_PARTY 和 CHILD_ID 的不同组合。我添加了一个 ORDER BY 以确保以某种合理的顺序返回结果。

祝你好运。

【讨论】:

  • 谢谢!这正是我所需要的!
【解决方案2】:

一种加入方式是:

Select distinct b.child_id         
        From voucher b, cc_authorization d, case e, episode g, invoice c, invoice_item f, svcperiod_info v        
        Where b.cc_authorization_id = d.cc_authorization_id  and d.subsidy_id = g.episode_id and g.case_id = e.case_id       
        and b.voucher_id = f.voucher_id and f.invoice_id = c.invoice_id and v.svcperiod_id = c.svcperiod_id
        and f.status = 8 and  f.net_amount > 0 and (v.end_dt >= '01-APR-17' and v.end_dt < '02-APR-17') and e.case_id<4000 and e.identifying_party in (Select distinct e1.identifying_party         
            From voucher b, cc_authorization d, case e1, episode g, invoice c, invoice_item f, svcperiod_info v        
            Where b.cc_authorization_id = d.cc_authorization_id  and d.subsidy_id = g.episode_id and g.case_id = e1.case_id       
            and b.voucher_id = f.voucher_id and f.invoice_id = c.invoice_id and v.svcperiod_id = c.svcperiod_id
            and f.status = 8 and  f.net_amount > 0 and (v.end_dt >= '01-APR-17' and v.end_dt < '02-APR-17') and e1.case_id<4000);

请注意,我在表case 的子查询中使用了e1 别名。您可能需要为 sub=query 中的其他表使用不同的别名。

【讨论】:

  • 感谢您的反馈。我想我希望有一个更简洁的方法,但也许这是唯一的方法!
  • 可以做一些优化,但我认为需要了解更多关于表和关系的细节。
  • 是的,我也是这么认为的……它们目前太大太复杂,无法提供一段简单的信息。谢谢你的回答!
【解决方案3】:

根据其他人的建议以及您对查询的看法,这可能会奏效:

SELECT DISTINCT v.child_id
FROM voucher v
INNER JOIN cc_authorization cca ON v.cc_authorization_id = cca.cc_authorization_id
INNER JOIN episode ep cca.subsidy_id = ep.episode_id
INNER JOIN case ca ON ep.case_id = ca.case_id
INNER JOIN invoice_item it ON d.voucher_id = it.voucher_id
INNER JOIN invoice inv ON it.invoice_id = inv.invoice_id
INNER JOIN svcperiod_info spi ON inv.svcperiod_id = spi.svcperdiod_id
WHERE it.status = 8
AND it.net_amount > 0
AND (spi.end_dt >= DATE'01-APR-17' AND spi.end_dt < DATE'02-APR-17')
AND ca.case_id < 4000
AND ca.identifying_party IN (
  SELECT DISTINCT ca1.identifying_party
  FROM voucher v
  INNER JOIN cc_authorization cca ON v.cc_authorization_id = cca.cc_authorization_id
  INNER JOIN episode ep cca.subsidy_id = ep.episode_id
  INNER JOIN case ca1 ON ep.case_id = ca.case_id
  INNER JOIN invoice_item it ON d.voucher_id = it.voucher_id
  INNER JOIN invoice inv ON it.invoice_id = inv.invoice_id
  INNER JOIN svcperiod_info spi ON inv.svcperiod_id = spi.svcperdiod_id
  WHERE it.status = 8
  AND it.net_amount > 0
  AND (spi.end_dt >= DATE'01-APR-17' AND spi.end_dt < DATE'02-APR-17')
  AND ca.case_id < 4000
);

请注意我如何将连接更改为使用 ANSI 标准连接并为每个表指定更合适的别名。

但是,如果您可以提供有关数据的更多信息,我认为它可以改进。为什么我们需要在内部和外部查询中运行相同的逻辑?它们是否可以合并到同一个查询中(例如 SELECT DISTINCT v.child_id、ca1.identifying_party...)?

【讨论】:

  • 原作者所做的是从第一个查询创建一个列表,然后循环通过第二个查询从创建的列表中提取一个值 (ca.identifying_party)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-14
  • 1970-01-01
相关资源
最近更新 更多