SQL Developer - 在查询的 where 子句中使用开始和结束日期变量

发布于 2024-09-30 05:15:38 字数 3522 浏览 8 评论 0原文

我每天运行一个查询,需要 StartDateEndDate 值。 StartDateEndDate 曾经是手动输入,但我试图摆脱这种情况并计算 StartDateEndDate< /code> 在查询中使用。我开发了代码来捕获变量中的 StartDateEndDate

DECLARE

    c_DateMask VARCHAR2(20) := 'DD-Mon-YYYY';
    c_TimeMask VARCHAR2(20) := 'HH24:MI';

    v_Month char(4) := 'Prev'; 
    v_StartDate date; 
    v_EndDate date; 
    v_Environment char(7) := 'Prod';  

BEGIN

    if v_MONTH = 'Prev'
        THEN 
            select TO_DATE ('01-' || TO_CHAR (ADD_MONTHS (SYSDATE, -1),'mon-yyyy')) into v_StartDate from dual; 
            select Last_day(TO_DATE('01-' || TO_CHAR (ADD_MONTHS (SYSDATE, -1),'mon-yyyy'))) into v_EndDate from dual;
        ELSE
            select TO_DATE ('01-' || TO_CHAR (ADD_MONTHS (SYSDATE, 0),'mon-yyyy')) into v_StartDate from dual;
            CASE
                WHEN v_Environment = 'Prod'
                    THEN
                        -- Production Environment --
                          select 
                              to_char(sysdate, 'dd-Mon-yyyy ') ||
                              case 
                                  when to_char(sysdate, 'mi') between 00 and 20
                                    then to_char(sysdate, 'hh24')-1||':58'||':00' 
                                  when to_char(sysdate, 'mi') between 21 and 40
                                    then to_char(sysdate, ' hh24')||':18'||':00' 
                                  when to_char(sysdate, 'mi') between 41 and 60
                                    then to_char(sysdate, ' hh24')||':38'||':00'
                              END 
                          into v_EndDate from dual;
                WHEN v_Environment = 'OldTest'
                    THEN
                       -- Test Environment --
                            select 
                                to_char(sysdate, 'dd-Mon-yyyy ') ||
                                case 
                                when to_char(sysdate, 'mi') between 10 and 30
                                    then to_char(sysdate, 'hh24')||':08'||':00'
                                when to_char(sysdate, 'mi') between 31 and 50
                                    then to_char(sysdate, ' hh24')||':28'||':00' 
                                when to_char(sysdate, 'mi') between 51 and 60
                                    then to_char(sysdate, ' hh24')||':48'||':00'
                                END 
                            into v_EndDate from dual;
            end case;    
    end if;

然后我想在下面的 select 语句中使用这些变量:

    -----------------
    /* KPI Figures */
    -----------------

    SELECT 
        SysDate as RunTime
        , v_StartDate
        , v_EndDate
        , TTM_OFF_CONTRIBUTOR
        , SUM(NVL(TTM_PER_OFF_FEE,0)) Fees
    FROM  [Table]
    Where 
        TTM_PROCESSED_DATE    >= v_StartDate
        AND TTM_PROCESSED_DATE    <= v_EndDate
    group by SysDate, v_StartDate, v_EndDate, TTM_OFF_CONTRIBUTOR

END;

一切正常,直到我尝试使用 KPI 数字查询中的变量值。我缺少什么?

更新:

关于菲尔的回答:我尝试过,但没有成功,并且收到以下错误:

PLS-00428:此 SELECT 语句中应包含 INTO 子句。

我确信我昨天看到了另一个回复,该回复现在已经不再涉及能够为变量或其他内容分配多个值。

这是我所需要的吗?我该怎么做?

I have a query that I run everyday that requires a StartDate and EndDate value. The StartDate and EndDate used to be a manual input but I am trying to get away from that and calculate the StartDate and EndDate to be used in the query. I've developed code to capture the StartDate and EndDate in variables:

DECLARE

    c_DateMask VARCHAR2(20) := 'DD-Mon-YYYY';
    c_TimeMask VARCHAR2(20) := 'HH24:MI';

    v_Month char(4) := 'Prev'; 
    v_StartDate date; 
    v_EndDate date; 
    v_Environment char(7) := 'Prod';  

BEGIN

    if v_MONTH = 'Prev'
        THEN 
            select TO_DATE ('01-' || TO_CHAR (ADD_MONTHS (SYSDATE, -1),'mon-yyyy')) into v_StartDate from dual; 
            select Last_day(TO_DATE('01-' || TO_CHAR (ADD_MONTHS (SYSDATE, -1),'mon-yyyy'))) into v_EndDate from dual;
        ELSE
            select TO_DATE ('01-' || TO_CHAR (ADD_MONTHS (SYSDATE, 0),'mon-yyyy')) into v_StartDate from dual;
            CASE
                WHEN v_Environment = 'Prod'
                    THEN
                        -- Production Environment --
                          select 
                              to_char(sysdate, 'dd-Mon-yyyy ') ||
                              case 
                                  when to_char(sysdate, 'mi') between 00 and 20
                                    then to_char(sysdate, 'hh24')-1||':58'||':00' 
                                  when to_char(sysdate, 'mi') between 21 and 40
                                    then to_char(sysdate, ' hh24')||':18'||':00' 
                                  when to_char(sysdate, 'mi') between 41 and 60
                                    then to_char(sysdate, ' hh24')||':38'||':00'
                              END 
                          into v_EndDate from dual;
                WHEN v_Environment = 'OldTest'
                    THEN
                       -- Test Environment --
                            select 
                                to_char(sysdate, 'dd-Mon-yyyy ') ||
                                case 
                                when to_char(sysdate, 'mi') between 10 and 30
                                    then to_char(sysdate, 'hh24')||':08'||':00'
                                when to_char(sysdate, 'mi') between 31 and 50
                                    then to_char(sysdate, ' hh24')||':28'||':00' 
                                when to_char(sysdate, 'mi') between 51 and 60
                                    then to_char(sysdate, ' hh24')||':48'||':00'
                                END 
                            into v_EndDate from dual;
            end case;    
    end if;

I then want to use the variables in my select statement below:

    -----------------
    /* KPI Figures */
    -----------------

    SELECT 
        SysDate as RunTime
        , v_StartDate
        , v_EndDate
        , TTM_OFF_CONTRIBUTOR
        , SUM(NVL(TTM_PER_OFF_FEE,0)) Fees
    FROM  [Table]
    Where 
        TTM_PROCESSED_DATE    >= v_StartDate
        AND TTM_PROCESSED_DATE    <= v_EndDate
    group by SysDate, v_StartDate, v_EndDate, TTM_OFF_CONTRIBUTOR

END;

It all works up until when I try to use the variable values in the KPI Figures query. What am I missing?

Update:

Regarding Phil's answer: I tried but it didn't work and I get the following error:

PLS-00428: an INTO clause is expected in this SELECT statement.

I am sure I saw another response yesterday which is now gone relating to being able to assign multiple values to variables or something.

Is that what I need and how would I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧夏天 2024-10-07 05:15:39

变量 v_StartDate 和 v_EndDate 仅在声明它们的 PL/SQL 块的范围内。看来您随后尝试在单独的查询中在块之外使用它们。为此,您需要在 PL/SQL 块外部创建 SQL Developer 绑定变量,如下所示:

var v_start_date varchar2(11)
var v_end_date varchar2(11)

然后在 PL/SQL 块和 SQL 查询中将这些变量引用为绑定变量:

declare
  ...
begin
  ....
  :v_start_date := '01-' || TO_CHAR (ADD_MONTHS (SYSDATE, -1), 'mon-yyyy');
  :v_end_date := TO_CHAR(Last_day(TO_DATE('01-' 
                 || TO_CHAR (ADD_MONTHS (SYSDATE, -1),'mon-yyyy'))));
  -- (NB No need to select from dual)
  ...
end;

SQL:

...
Where 
TTM_PROCESSED_DATE    >= TO_DATE(:v_StartDate)
AND TTM_PROCESSED_DATE    <= TO_DATE(:v_EndDate)

请注意,这些变量不能用DATE 类型,因此需要将它们转换回查询中的日期(使用正确的格式掩码)。

The variables v_StartDate and v_EndDate are only in scope within the PL/SQL block where they are declared. It looks like you are then trying to use them outside the block in a separate query. To do that you will need to create SQL Developer bind variables outside the PL/SQL block like this:

var v_start_date varchar2(11)
var v_end_date varchar2(11)

Then reference these as bind variables in both the PL/SQL block and the SQL query:

declare
  ...
begin
  ....
  :v_start_date := '01-' || TO_CHAR (ADD_MONTHS (SYSDATE, -1), 'mon-yyyy');
  :v_end_date := TO_CHAR(Last_day(TO_DATE('01-' 
                 || TO_CHAR (ADD_MONTHS (SYSDATE, -1),'mon-yyyy'))));
  -- (NB No need to select from dual)
  ...
end;

SQL:

...
Where 
TTM_PROCESSED_DATE    >= TO_DATE(:v_StartDate)
AND TTM_PROCESSED_DATE    <= TO_DATE(:v_EndDate)

Note that these variables cannot be declared with a type of DATE, so they need to be converted back to dates in the query (using the correct format mask).

不甘平庸 2024-10-07 05:15:39

我建议您将开始日期/结束日期包装在两个函数(存储过程)中,

create or replace function get_startdate(p_month in varchar2, p_env in varchar2)
return date
is
  l_return date;
begin
   ... logic goes here ...
   return l_return;
end;

与结束日期类似。

然后在查询中使用这些函数:

SELECT 
    SysDate as RunTime
    , get_startdate('Prev', 'Prod')
    , get_enddate('Prev', 'Prod')
    , TTM_OFF_CONTRIBUTOR
    , SUM(NVL(TTM_PER_OFF_FEE,0)) Fees
FROM  [Table]
Where 
    TTM_PROCESSED_DATE    >= get_startdate('Prev', 'Prod')
    AND TTM_PROCESSED_DATE    <= get_enddate('Prev', 'Prod')
group by SysDate, get_startdate('Prev', 'Prod'), get_enddate('Prev', 'Prod'), TTM_OFF_CONTRIBUTOR

旁注:请考虑更简洁的版本来确定一个月的第一天和最后一天。您还可以在不使用 SELECT INTO 的情况下为变量赋值,例如

startdate := trunc(sysdate, 'MM'); -- first day of current month
enddate := last_day(trunc(sysdate, 'MM')); -- last day of current month

要以小时计算,您可以添加/减去分钟数,这比您所做的所有 to_date/to_char 转换更具可读性,例如祝您

enddate := trunc(sysdate, 'HH24');
case 
  when to_char(sysdate, 'mi') between 00 and 20 then enddate := enddate - 2/(24*60);
  when to_char(sysdate, 'mi') between 21 and 40 then enddate := enddate + 18/(24*60);
  when to_char(sysdate, 'mi') between 41 and 60 then enddate := enddate + 38/(24*60);
end; 

好运,马丁

I suggest you wrap the startdate/enddate in two functions (stored procedures)

create or replace function get_startdate(p_month in varchar2, p_env in varchar2)
return date
is
  l_return date;
begin
   ... logic goes here ...
   return l_return;
end;

Similar for enddate.

Then use those functions in your query:

SELECT 
    SysDate as RunTime
    , get_startdate('Prev', 'Prod')
    , get_enddate('Prev', 'Prod')
    , TTM_OFF_CONTRIBUTOR
    , SUM(NVL(TTM_PER_OFF_FEE,0)) Fees
FROM  [Table]
Where 
    TTM_PROCESSED_DATE    >= get_startdate('Prev', 'Prod')
    AND TTM_PROCESSED_DATE    <= get_enddate('Prev', 'Prod')
group by SysDate, get_startdate('Prev', 'Prod'), get_enddate('Prev', 'Prod'), TTM_OFF_CONTRIBUTOR

Sidenote: please consider a more concise version to determine first and last day of a month. You also can just assign a value to a variable without using SELECT INTO, e.g.

startdate := trunc(sysdate, 'MM'); -- first day of current month
enddate := last_day(trunc(sysdate, 'MM')); -- last day of current month

To calculate with hours, you could add/subtract a number of minutes, that's more readable than all the to_date/to_char conversions you do, e.g.

enddate := trunc(sysdate, 'HH24');
case 
  when to_char(sysdate, 'mi') between 00 and 20 then enddate := enddate - 2/(24*60);
  when to_char(sysdate, 'mi') between 21 and 40 then enddate := enddate + 18/(24*60);
  when to_char(sysdate, 'mi') between 41 and 60 then enddate := enddate + 38/(24*60);
end; 

Good luck, Martin

哆啦不做梦 2024-10-07 05:15:39

我认为问题出在您的查询和别名上。尝试

SELECT 
    SysDate as RunTime
    , v_StartDate AS StartDate
    , v_EndDate AS EndDate
    , TTM_OFF_CONTRIBUTOR
    , SUM(NVL(TTM_PER_OFF_FEE,0)) Fees
FROM  [Table]
Where 
    TTM_PROCESSED_DATE    >= v_StartDate
    AND TTM_PROCESSED_DATE    <= v_EndDate
group by RunTime, StartDate, EndDate, TTM_OFF_CONTRIBUTOR

I think the issue is with your query and aliases. Try

SELECT 
    SysDate as RunTime
    , v_StartDate AS StartDate
    , v_EndDate AS EndDate
    , TTM_OFF_CONTRIBUTOR
    , SUM(NVL(TTM_PER_OFF_FEE,0)) Fees
FROM  [Table]
Where 
    TTM_PROCESSED_DATE    >= v_StartDate
    AND TTM_PROCESSED_DATE    <= v_EndDate
group by RunTime, StartDate, EndDate, TTM_OFF_CONTRIBUTOR
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文