[英]Return multiple values in a single oracle sql statement
Below is a query that is in java 以下是Java中的查询
SELECT achieve_STATUS_CD
FROM achievemnt
WHERE env_id = '?' AND ROWNUM = 1
ORDER BY achive_status_dt
which needs to return value 'Y' based from another two tables enrollment, provision with below conditions 需要从另外两个表的注册中返回值“ Y”,并满足以下条件
for the rest all conditions it should return the values from original query (SELECT achieve_STATUS_CD FROM achievemnt WHERE env_id = '?' AND ROWNUM = 1 ORDER BY achive_status_dt) 对于其余所有条件,它都应返回原始查询的值(SELECT Achieve_STATUS_CD FROM Achievemnt WHERE env_id ='?'AND ROWNUM = 1 ORDER BY achive_status_dt)
achievemnt is child table of enrollment Achievemnt是注册的子表
How can i write this logic ? 我该如何写这个逻辑?
I have written the below query but it has env_id at 2 places but we cant change that in our java for now so i need to write in a single query which accepts env_id only at once 我已经写了下面的查询,但是它在2个地方有env_id,但是我们现在不能在Java中更改它,所以我需要写一个只接受一次env_id的查询
WITH TMP
AS (SELECT 'Y' AS achieve_STATUS_CD, env_id
FROM enrollment r, provision a
WHERE r.prov_id = a.prov_id
AND r.achieve_intent = '2'
AND a.BEGIN_DT >=
TO_DATE (
05/01/2011,
'MM/DD/YYYY')
AND a.RELEASE_DT <= SYSDATE AND R.env_ID = '?')
SELECT NVL (F.achieve_STATUS_CD,TMP.achieve_STATUS_CD)
FROM TMP FULL OUTER JOIN
(SELECT achieve_STATUS_CD
FROM achievemnt
WHERE env_id = '?' AND
ROWNUM = 1
ORDER BY achive_status_dt
) F
ON TMP.env_ID = F.env_ID;
Your initial query is highly likely to be incorrect. 您的初始查询很可能不正确。 The
rownum = 1
predicate in this query is applied before the ORDER BY
so you're asking for an arbitrary row where the env_id
is whatever bind value and then sorting the resulting single row. 此查询中的
rownum = 1
谓词在ORDER BY
之前应用,因此您要询问一个任意行,其中env_id
是任何绑定值,然后对所得的单行进行排序。 Sorting a single row is obviously pointless. 排序单行显然是毫无意义的。
SELECT achieve_STATUS_CD
FROM achievemnt
WHERE env_id = '?'
AND ROWNUM = 1
ORDER BY achive_status_dt
If you want to sort multiple rows and to pick the row with the first achive_status_dt
, you'd want something like 如果要对多行进行排序并选择第一个
achive_status_dt
的行,则需要类似
SELECT *
FROM (SELECT achieve_STATUS_CD
FROM achievemnt
WHERE env_id = '?'
ORDER BY achive_status_dt) a
WHERE a.ROWNUM = 1
If your actual question, though, is that the second query does what you want (which seems unlikely given the issue I just mentioned) but you want to do it with a single bind variable, you can simply add another CTE that selects the bind variable from dual
and then reference that CTE wherever you'd like 但是,如果您的实际问题是第二个查询满足您的要求(考虑到我刚才提到的问题,这似乎不太可能),但是您想使用单个绑定变量来执行此操作,则只需添加另一个选择绑定变量的CTE从
dual
,然后在任意位置引用该CTE
WITH env
AS (SELECT '?' env_id from dual)
,TMP
AS (SELECT 'Y' AS achieve_STATUS_CD, env_id
FROM enrollment r, provision a, env
WHERE r.prov_id = a.prov_id
AND r.achieve_intent = '2'
AND a.BEGIN_DT >=
TO_DATE (
05/01/2011,
'MM/DD/YYYY')
AND a.RELEASE_DT <= SYSDATE
AND R.env_ID = env.env_ID)
SELECT NVL (F.achieve_STATUS_CD,TMP.achieve_STATUS_CD)
FROM TMP FULL OUTER JOIN
(SELECT achieve_STATUS_CD
FROM achievemnt
join env
on achievement.env_id = env.env_id
WHERE ROWNUM = 1
ORDER BY achive_status_dt
) F
ON TMP.env_ID = F.env_ID;
Supposing that : 假设:
1- the question of rownum is correct (i agree with Justin) 1- rownum问题正确(我同意贾斯汀)
2- the achievemnt table is always populated 2-总是填充成就表
You can release the condition 您可以解除条件
AND R.env_ID = '?'
AND R.env_ID ='?'
on the TMP subquery. 在TMP子查询上。 In this case, it should be enough that the query is a LEFT outer join based on env_id.
在这种情况下,查询是基于env_id的LEFT外部联接就足够了。
So the full query should become like this (i don't have an sql console to test it) 因此完整的查询应该变成这样(我没有SQL控制台对其进行测试)
WITH TMP
AS (SELECT 'Y' AS achieve_STATUS_CD, env_id
FROM enrollment r, provision a
WHERE r.prov_id = a.prov_id
AND r.achieve_intent = '2'
AND a.BEGIN_DT >=
TO_DATE (
05/01/2011,
'MM/DD/YYYY')
AND a.RELEASE_DT <= SYSDATE ),
F
AS (SELECT TMP.achieve_STATUS_CD
FROM achievemnt
WHERE env_id = '?' AND
ROWNUM = 1
ORDER BY achive_status_dt)
SELECT NVL (TMP.achieve_STATUS_CD, F.achieve_STATUS_CD)
FROM F LEFT OUTER JOIN TMP
ON F.env_ID=TMP.env_ID;
Note that i inverted the NVL fields: if TMP.achieve_STATUS_CD is not null, ie if a row exists, that value, which is always Y, should be taken, otherwise the value from achievemnt. 请注意,我颠倒了NVL字段:如果TMP.achieve_STATUS_CD不为null,即,如果存在一行,则应采用始终为Y的值,否则应采用Achievemnt的值。
If the assuntion 2 is not true, you can invert the 2 subqueries in the outer join. 如果assuntion 2不正确,则可以反转外部联接中的2个子查询。
If you need the record from achievemnt with the oldest date, F may become something like this 如果您需要成就记录中最早的日期,F可能会变成这样
SELECT TMP.achieve_STATUS_CD, achive_status_dt, env_id, min(achive_status_dt) OVER(partition by end_id) min_date
FROM achievemnt
WHERE env_id = '?' AND
achive_status_dt=min_date
This is how I understand your question (and I may be completely wrong): If at least one enrollment/provision pair that matches your criteria exists for an env_id show 'Y', otherwise show the first achievement status for it. 这就是我对您的问题的理解方式(我可能完全错了):如果在env_id中显示“ Y”,至少存在一个与您的条件匹配的注册/设置对,否则显示其第一个成就状态。
select
case when exists
(
select *
from enrollment e
join provision p on p.prov_id = e.prov_id
where e.achieve_intent = '2'
and p.begin_dt >= date '2011-05-01'
and p.release_dt <= sysdate
and e.env_id = :env_id
) then 'Y'
else
(
select max(achieve_status_cd) keep (dense_rank first order by achive_status_dt)
from achievement
where env_id = :env_id
) as status
from dual;
If you want to have :env_id only once in your query, change it slightly to: 如果只想在查询中只使用一次:env_id,请将其稍微更改为:
select
case when exists
(
select ...
and e.env_id = main.env_id
) then 'Y'
else
(
select ...
where env_id = main.env_id
) as status
from (select :env_id as env_id from dual) main;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.