【问题标题】:Oracle SQL GROUP BY clause containing joins包含连接的 Oracle SQL GROUP BY 子句
【发布时间】:2019-05-17 09:21:11
【问题描述】:

我在正确编写此查询时遇到问题。下面是目标,我当前的查询,附件是构建和填充数据库的脚本。感谢您的帮助!

对于目录中的每张 DVD,显示其标题、长度、发行日期以及所有图书馆的所有客户已将其签出的次数。包括尚未签出的那些(显示为 0)。按标题对结果进行排序。

SELECT C.TITLE, D.LENGTH, C.RELEASE_DATE, COUNT(T.TRANSACTION_ID)
FROM catalog_item C
INNER JOIN dvd D ON D.CATALOG_ITEM_ID = C.CATALOG_ITEM_ID
INNER JOIN physical_item P ON P.CATALOG_ITEM_ID = C.CATALOG_ITEM_ID
LEFT OUTER JOIN transaction T ON T.PHYSICAL_ITEM_ID = P.PHYSICAL_ITEM_ID
GROUP BY C.TITLE;

先运行:https://drive.google.com/open?id=1PYAZV4KIfZtxP4eQn35zsczySsxDM7ls

第二次运行:https://drive.google.com/open?id=1pAzWmJqvD3o3n6YJqVUM6TtxDafKGd3f

编辑
我已经使查询正常工作,但还没有弄清楚如何让具有零结帐的 DVD 显示出来。以下是我更新的查询。

SELECT C.TITLE, D.LENGTH, C.RELEASE_DATE, COUNT(T.TRANSACTION_ID)
FROM catalog_item C
INNER JOIN dvd D ON D.CATALOG_ITEM_ID = C.CATALOG_ITEM_ID
INNER JOIN physical_item P ON P.CATALOG_ITEM_ID = C.CATALOG_ITEM_ID
LEFT OUTER JOIN transaction T ON T.PHYSICAL_ITEM_ID = P.PHYSICAL_ITEM_ID
GROUP BY C.TITLE, D.LENGTH, C.RELEASE_DATE;

已解决
在 GMB 的帮助下解决了这个问题。下面是最终查询!

SELECT C.TITLE, D.LENGTH, C.RELEASE_DATE, NVL(COUNT(T.TRANSACTION_ID), 0) AS NUMBER_OF_CHECKOUTS
FROM catalog_item C
INNER JOIN dvd D ON D.CATALOG_ITEM_ID = C.CATALOG_ITEM_ID
LEFT JOIN physical_item P ON P.CATALOG_ITEM_ID = C.CATALOG_ITEM_ID
LEFT JOIN transaction T ON T.PHYSICAL_ITEM_ID = P.PHYSICAL_ITEM_ID
GROUP BY C.TITLE, D.LENGTH, C.RELEASE_DATE
ORDER BY C.TITLE;

【问题讨论】:

  • A minimal reproducible example 包括 DBMS(带版本)、清晰的规范、剪切和粘贴和可运行代码(具有小的代表性输入)(将表格初始化格式化为表格)和可区分(因此有序)所需的输出.但是调试的绝对基础说:表明你的程序在通过(子)表达式时做了你期望的事情,说明它是什么,并表明它实际上是通过增量输出做到的。在添加您无法修复的问题代码时,请研究(手册和网络)。重复,尽量减少工作代码和错误代码。然后询问工作示例和非工作示例之间的(小)差异。

标签: sql join oracle11g group-by


【解决方案1】:

您的第二个查询肯定比第一个更好,因为它有正确的GROUP BY 子句。

如果没有看到完整的表结构,很难提供 100% 确定的响应,但是如果输出中仍然缺少 0 个签出的记录,则意味着您的 INNER JOINs 之一不匹配。换言之,您的目录中有 DVD,它们要么不在 dvd 表中,要么不在 physical_item 表中。由于两个表看起来都像参考表,这可能表明您的数据存在差异。我建议将所有 INNER JOINs 更改为 LEFT JOINs 以解决此问题。

另外请注意,如果 DVD 没有发生结帐,则表达式 COUNT(T.TRANSACTION_ID) 将产生 NULL :因此您希望将其包装在 NVL 函数中来处理这种情况。

新查询:

SELECT C.TITLE, D.LENGTH, C.RELEASE_DATE, NVL(COUNT(T.TRANSACTION_ID), 0)
FROM catalog_item C
LEFT JOIN dvd D ON D.CATALOG_ITEM_ID = C.CATALOG_ITEM_ID
LEFT JOIN physical_item P ON P.CATALOG_ITEM_ID = C.CATALOG_ITEM_ID
LEFT JOIN transaction T ON T.PHYSICAL_ITEM_ID = P.PHYSICAL_ITEM_ID
GROUP BY C.TITLE, D.LENGTH, C.RELEASE_DATE;

【讨论】:

  • 非常感谢!我对其进行了一些调整并编辑了我的问题以纳入您的反馈。第一个连接应该是 INNER,因为我们只想要 DVD,而 LEFT JOIN 也会拉书。再次感谢您!
  • 欢迎@RyanCohan,很高兴能帮上忙!
  • COUNT() 永远不会返回 NULLNVL() 是不必要的。
  • 这里假设T.TRANSACTION_ID被声明为NOT NULL,或者每个非NULL值代表一个有效的结账(如果NULLs被允许)。
猜你喜欢
  • 1970-01-01
  • 2012-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多