select 基于 oracle 中存在的行数的单行
select single row based on count of rows present oracle
我使用查询得到了以下 table,现在我想根据下面解释的条件获取单个记录并将其分配给两个变量,即声明的 v_dte_meeting
和 v_status_meeting
在我的存储过程中,
Dte_Meeting| Ststus_Meeting
########################
15-Oct-14 | Due
30-Oct-14 | Due
15-Dec-14 | Init
30-Dec-14 | Init
30-Nov-15 | Approved
我想根据以下条件为这些变量赋值:
- 如果一个或多个记录以 Status_Meeting 作为 'Due' 则分配 v_dte_meeting 具有 'Due' 状态的最大日期并分配 v_status_meeting 值'Due'
- 如果上述条件不成立,则检查是否有单个或多个记录以 Ststus_Meeting 作为 'Init' 如果是,则分配 v_dte_meeting 最大日期 'Init' 状态并为 v_status_meeting 赋值 'Init'
- 如果两个条件都失败,则为两个变量分配 NULL 值
请帮助我在 Oracle 中以最佳方式做到这一点
一种方法使用聚合:
select (case when sum(case when status_meeting = 'Due' then 1 else 0 end) > 0
then max(case when status_meeting = 'Due' dte_meeting end)
when sum(case when status_meeting = 'Init' then 1 else 0 end) > 0
then max(case when status_meeting = 'Init' then dte_meeting end)
end),
(case when sum(case when status_meeting = 'Due' then 1 else 0 end) > 0
then'Due'
when sum(case when status_meeting = 'Init' then 1 else 0 end) > 0
then 'Init'
end)
into v_dte_meeting, v_status_meeting
from t;
但是,我认为更简单的版本只使用 order by
:
select max(dte_meeting), max(status_meeting)
into v_dte_meeting, v_status_meeting
from (select t.*
from t
where status_meeting in ('Due', 'Init')
order by (case when status_meeting = 'Due' then 1
when status_meeting = 'Init' then 2
end)
) t
where rownum = 1;
max()
只是为了保证正好返回一行。
希望这对您有所帮助。我只展示 SELECT 语句(我没有创建变量,所以我没有选择 INTO,但这不是你的难点,你知道怎么做。)我使用子查询分解(WITH 子句),我相信只能在 >= 11 的版本中使用,否则你可以重写以将子查询放在它们所属的位置。
注意rank()的使用;在 Gordon 的解决方案中,他将在所有行中获取 max(dte),而不仅仅是状态 = 'Due' 的行,因此它不可能像他写的那么简单。编辑:我也看不到他在哪里选择 NULL,如果 'Due' 和 'Init' 都不存在则为 NULL。 (抱歉辱骂,这应该是对他的回答的评论,我没有权限。)
WITH t (Date_Meeting, Status_Meeting) AS
(
SELECT TO_DATE('15-OCT-14', 'DD-MON-YY'), 'Due' FROM dual UNION ALL
SELECT TO_DATE('30-OCT-14', 'DD-MON-YY'), 'Due' FROM dual UNION ALL
SELECT TO_DATE('15-DEC-14', 'DD-MON-YY'), 'Init' FROM dual UNION ALL
SELECT TO_DATE('30-DEC-14', 'DD-MON-YY'), 'Init' FROM dual UNION ALL
SELECT TO_DATE('15-NOV-15', 'DD-MON-YY'), 'Approved' FROM dual
),
s (Date_Meeting, Status_Meeting) AS
(
SELECT Date_Meeting, Status_Meeting FROM t
WHERE Status_Meeting = 'Due' OR Status_Meeting = 'Init'
UNION ALL SELECT NULL, NULL FROM dual -- To ensure you have the nulls if needed
),
r (Date_Meeting, Status_Meeting, rk) AS
(
SELECT Date_Meeting, Status_Meeting,
RANK() OVER (ORDER BY DECODE(Status_Meeting, 'Due', 0, 'Init', 1, 2),
Date_Meeting DESC) -- make sure you understand this
FROM s
)
SELECT Date_Meeting, Status_Meeting FROM r WHERE rk = 1
/
结果:
DATE_MEET STATUS_M
--------- --------
30-OCT-14 Due
1 row selected.
我使用查询得到了以下 table,现在我想根据下面解释的条件获取单个记录并将其分配给两个变量,即声明的 v_dte_meeting
和 v_status_meeting
在我的存储过程中,
Dte_Meeting| Ststus_Meeting
########################
15-Oct-14 | Due
30-Oct-14 | Due
15-Dec-14 | Init
30-Dec-14 | Init
30-Nov-15 | Approved
我想根据以下条件为这些变量赋值:
- 如果一个或多个记录以 Status_Meeting 作为 'Due' 则分配 v_dte_meeting 具有 'Due' 状态的最大日期并分配 v_status_meeting 值'Due'
- 如果上述条件不成立,则检查是否有单个或多个记录以 Ststus_Meeting 作为 'Init' 如果是,则分配 v_dte_meeting 最大日期 'Init' 状态并为 v_status_meeting 赋值 'Init'
- 如果两个条件都失败,则为两个变量分配 NULL 值
请帮助我在 Oracle 中以最佳方式做到这一点
一种方法使用聚合:
select (case when sum(case when status_meeting = 'Due' then 1 else 0 end) > 0
then max(case when status_meeting = 'Due' dte_meeting end)
when sum(case when status_meeting = 'Init' then 1 else 0 end) > 0
then max(case when status_meeting = 'Init' then dte_meeting end)
end),
(case when sum(case when status_meeting = 'Due' then 1 else 0 end) > 0
then'Due'
when sum(case when status_meeting = 'Init' then 1 else 0 end) > 0
then 'Init'
end)
into v_dte_meeting, v_status_meeting
from t;
但是,我认为更简单的版本只使用 order by
:
select max(dte_meeting), max(status_meeting)
into v_dte_meeting, v_status_meeting
from (select t.*
from t
where status_meeting in ('Due', 'Init')
order by (case when status_meeting = 'Due' then 1
when status_meeting = 'Init' then 2
end)
) t
where rownum = 1;
max()
只是为了保证正好返回一行。
希望这对您有所帮助。我只展示 SELECT 语句(我没有创建变量,所以我没有选择 INTO,但这不是你的难点,你知道怎么做。)我使用子查询分解(WITH 子句),我相信只能在 >= 11 的版本中使用,否则你可以重写以将子查询放在它们所属的位置。
注意rank()的使用;在 Gordon 的解决方案中,他将在所有行中获取 max(dte),而不仅仅是状态 = 'Due' 的行,因此它不可能像他写的那么简单。编辑:我也看不到他在哪里选择 NULL,如果 'Due' 和 'Init' 都不存在则为 NULL。 (抱歉辱骂,这应该是对他的回答的评论,我没有权限。)
WITH t (Date_Meeting, Status_Meeting) AS
(
SELECT TO_DATE('15-OCT-14', 'DD-MON-YY'), 'Due' FROM dual UNION ALL
SELECT TO_DATE('30-OCT-14', 'DD-MON-YY'), 'Due' FROM dual UNION ALL
SELECT TO_DATE('15-DEC-14', 'DD-MON-YY'), 'Init' FROM dual UNION ALL
SELECT TO_DATE('30-DEC-14', 'DD-MON-YY'), 'Init' FROM dual UNION ALL
SELECT TO_DATE('15-NOV-15', 'DD-MON-YY'), 'Approved' FROM dual
),
s (Date_Meeting, Status_Meeting) AS
(
SELECT Date_Meeting, Status_Meeting FROM t
WHERE Status_Meeting = 'Due' OR Status_Meeting = 'Init'
UNION ALL SELECT NULL, NULL FROM dual -- To ensure you have the nulls if needed
),
r (Date_Meeting, Status_Meeting, rk) AS
(
SELECT Date_Meeting, Status_Meeting,
RANK() OVER (ORDER BY DECODE(Status_Meeting, 'Due', 0, 'Init', 1, 2),
Date_Meeting DESC) -- make sure you understand this
FROM s
)
SELECT Date_Meeting, Status_Meeting FROM r WHERE rk = 1
/
结果:
DATE_MEET STATUS_M
--------- --------
30-OCT-14 Due
1 row selected.