Oracle:Select Min with Where 子句

Oracle: Select Min with Where Clause

我正在尝试 运行 针对 Oracle 数据库执行以下语句并收到缺少表达式的消息。我怀疑问题是因为 MINOVERLAP 和 MAXOVERLAP 的 SELECT 不将 OVERLAPS 识别为 table,但我现在被卡住了。我在名为 Qlikview 的工具中 运行 宁此查询,因此没有创建临时 tables 等的好处。如果可能,它需要作为单个查询完成。

SELECT UCR, TR,
SELECT(MIN(OVERLAP_START_DT)
FROM OVERLAPS
WHERE OVERLAPS.UCR=UCR
AND OVERLAPS.TR  <=TR) AS MINOVERLAP
SELECT(MAX(OVERLAP_END_DT)
FROM OVERLAPS
WHERE OVERLAPS.UCR=UCR
AND OVERLAPS.TR  <=TR) AS MAXOVERLAP
FROM
  (SELECT DISTINCT REF_WORKFLOW.UCR,
    REF_WORKFLOW.TR,
    OVERLAP_START_DT,
    OVERLAP_END_DT
  FROM CDW.REF_WORKFLOW
  JOIN CDW.REF_WEL_PREV_TR_OVERLAP
  ON REF_WEL_PREV_TR_OVERLAP.WORKFLOW_SID=REF_WORKFLOW.WORKFLOW_SID
  JOIN CDW.REF_TRANS_PART_LINE
  ON REF_TRANS_PART_LINE.UCR       =REF_WORKFLOW.UCR
  AND REF_TRANS_PART_LINE.TR       =REF_WORKFLOW.TR
  AND REF_TRANS_PART_LINE.BUREAU_ID='SY'
  JOIN CDW.REF_WORKFLOW_EVENT
  ON REF_WORKFLOW_EVENT.TRANS_PART_LINE_SID            =REF_TRANS_PART_LINE.TRANS_PART_LINE_SID
  WHERE REF_WORKFLOW.BUREAU_ID                         = 'SY'
  AND REF_TRANS_PART_LINE.PARTICIPANT_TRANS_ROLE_CODE IN('AGREEMENT PARTY','LEAD')
  AND REF_WEL_PREV_TR_OVERLAP.OVERLAP_ELAPSED_DURATION >0
  AND REF_WORKFLOW_EVENT.WORKFLOW_EVENT_DT            >= TO_DATE('24/04/2015','DD/MM/YYYY')
  ) OVERLAPS;

您在第 5 行缺少一个逗号:

SELECT UCR, TR,
SELECT(MIN(OVERLAP_START_DT)
FROM OVERLAPS
WHERE OVERLAPS.UCR=UCR
AND OVERLAPS.TR  <=TR) AS MINOVERLAP, -- <<< here
SELECT(MAX(OVERLAP_END_DT)
FROM OVERLAPS
WHERE OVERLAPS.UCR=UCR
AND OVERLAPS.TR  <=TR) AS MAXOVERLAP
FROM
  (SELECT DISTINCT REF_WORKFLOW.UCR,
    REF_WORKFLOW.TR,
    OVERLAP_START_DT,
    OVERLAP_END_DT
  FROM CDW.REF_WORKFLOW
  JOIN CDW.REF_WEL_PREV_TR_OVERLAP
  ON REF_WEL_PREV_TR_OVERLAP.WORKFLOW_SID=REF_WORKFLOW.WORKFLOW_SID
  JOIN CDW.REF_TRANS_PART_LINE
  ON REF_TRANS_PART_LINE.UCR       =REF_WORKFLOW.UCR
  AND REF_TRANS_PART_LINE.TR       =REF_WORKFLOW.TR
  AND REF_TRANS_PART_LINE.BUREAU_ID='SY'
  JOIN CDW.REF_WORKFLOW_EVENT
  ON REF_WORKFLOW_EVENT.TRANS_PART_LINE_SID            =REF_TRANS_PART_LINE.TRANS_PART_LINE_SID
  WHERE REF_WORKFLOW.BUREAU_ID                         = 'SY'
  AND REF_TRANS_PART_LINE.PARTICIPANT_TRANS_ROLE_CODE IN('AGREEMENT PARTY','LEAD')
  AND REF_WEL_PREV_TR_OVERLAP.OVERLAP_ELAPSED_DURATION >0
  AND REF_WORKFLOW_EVENT.WORKFLOW_EVENT_DT            >= TO_DATE('24/04/2015','DD/MM/YYYY')
  ) OVERLAPS;

getting a missing expression message

您使用的是内联视图,但缺少逗号

这里:

AND OVERLAPS.TR  <=TR) AS MINOVERLAP
SELECT(MAX(OVERLAP_END_DT)

为什么不使用 WITH 子句 a.k.a 子查询分解 特性。对于 MIN 和 MAX 计算,使用 with 子句,然后在 filter predicate.

中使用它

除了缺少逗号外,您的子查询还需要正确地括在括号中;而你已经拥有的那些是不平衡的。或者更确切地说,在错误的地方;您目前以 SELECT(MIN... 开头,而应该是 (SELECT MIN...。将左括号移动到子查询的 SELECT 之前,而不是添加另一组。

所以你需要:

SELECT UCR, TR,
(SELECT MIN(OVERLAP_START_DT)
FROM OVERLAPS
WHERE OVERLAPS.UCR=UCR
AND OVERLAPS.TR  <=TR) AS MINOVERLAP,
(SELECT MAX(OVERLAP_END_DT)
FROM OVERLAPS
WHERE OVERLAPS.UCR=UCR
AND OVERLAPS.TR  <=TR) AS MAXOVERLAP
FROM
  (SELECT DISTINCT ...
  ) OVERLAPS;

但是正如您所怀疑的那样,您的 OVERLAPS 内联视图不在这些子查询的范围内。如果您的工具支持 CTE(有些很挑剔),您可以改用 CTE:

WITH OVERLAPS AS (
SELECT DISTINCT ...
)
SELECT UCR, TR,
(SELECT MIN(OVERLAP_START_DT)
FROM OVERLAPS
WHERE OVERLAPS.UCR=UCR
AND OVERLAPS.TR  <=TR) AS MINOVERLAP,
(SELECT MAX(OVERLAP_END_DT)
FROM OVERLAPS
WHERE OVERLAPS.UCR=UCR
AND OVERLAPS.TR  <=TR) AS MAXOVERLAP
FROM OVERLAPS;

不过你的逻辑还是有问题的。我认为您正在尝试进行关联,但您的条件将永远为真;例如这个:

WHERE OVERLAPS.UCR=UCR

... 将每行中的值与其自身进行比较,因此将始终计算为真(除非该值为空)。

您可能会发现使用带有窗口子句、CTE 或内联视图的 min/max 的分析版本更简单:

SELECT UCR, TR,
  MIN(OVERLAP_START_DT) OVER (PARTITION BY UCR ORDER BY TR
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS MINOVERLAP,
  MAX(OVERLAP_END_DT) OVER (PARTITION BY UCR ORDER BY TR
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS MAXOVERLAP
FROM
  (SELECT DISTINCT ...
  ) OVERLAPS;

大部分未经测试,因为我们没有任何数据或预期结果,但希望能给您一些指示。

SQL Fiddle 显示带有子查询的 CTE,由于上述相关性问题导致结果不正确;和分析方法。显然,使用了一些虚构的数据行。

如果您由于某种原因不能使用分析函数,您可以通过在子查询中为 CTE 设置别名来解决关联问题:

WITH OVERLAPS (UCR, TR, OVERLAP_START_DT, OVERLAP_END_DT) AS (
  SELECT DISTINCT ...
)
SELECT UCR, TR,
  (SELECT MIN(O2.OVERLAP_START_DT)
  FROM OVERLAPS O2
  WHERE O2.UCR = OVERLAPS.UCR
  AND O2.TR <= OVERLAPS.TR) AS MINOVERLAP,
  (SELECT MAX(O2.OVERLAP_END_DT)
  FROM OVERLAPS O2
  WHERE O2.UCR = OVERLAPS.UCR
  AND O2.TR <= OVERLAPS.TR) AS MAXOVERLAP
FROM OVERLAPS;

SQL Fiddle.