【问题标题】:get all the tables within a date range获取日期范围内的所有表格
【发布时间】:2022-01-05 00:24:34
【问题描述】:

我有许多结构和列相同但名称不同的每周备份表,其中包含一些特定于用户的信息。

user_details
user_details_20211126
user_details_20211119
user_details_20211112
and so on....

现在我想查找某个日期范围内的表格,例如:如果我选择日期范围为 2021-11-202021-11-13,那么获取的表格将是 user_details, user_details_20211126, user_details_20211119,以便在包含 union 的查询中使用它们对所有获取的表进行操作。 关于如何做到这一点的任何想法?

【问题讨论】:

  • 你应该有1个表并使用索引来访问数据,你当前的结构可能会导致大量问题并且违反数据库设计原则。
  • 但是我有这么多表你知道如何获取所需的数据
  • stackoverflow.com/questions/9898610/… 是一个开始,它允许您列出表格。但理想情况下,您应该重做表格,而不是这样做。
  • 你可以查询你的数据库的表目录
  • 这种设计模式会给您带来痛苦的世界,“最佳”可行的解决方案将取决于您尚未标记的特定数据库平台。您的数据应该在一个表中,并带有日期列 - 很简单。

标签: php sql database logic


【解决方案1】:

正如已经评论的那样,这是一个多么糟糕的想法……你不应该那样做。顺便说一下,一个带有DATE 数据类型列的表应该这样做。我建议你改用它 - 越早越好。


同时 - 虽然您没有命名您使用的数据库,而我使用的是 Oracle - 这就是您可能需要做的事情,无论数据库如何:某种动态 SQL必须“动态地”编写SELECT 语句,仅使用满足条件的表。由于您必须从数据字典中获取它们的名称,因此您没有太多选择,但 - 正如我所说 - 动态 SQL。

好的,给你。

设置日期格式(您不必这样做):

SQL> alter session set nls_date_format = 'dd.mm.yyyy';

Session altered.

名称为user_details_something的表:

SQL> select table_name
  2  from user_tables
  3  where table_name like 'USER_DETAILS%'
  4  order by table_name;

TABLE_NAME
------------------------------
USER_DETAILS
USER_DETAILS_20211126
USER_DETAILS_20211127
USER_DETAILS_20211128

如何只选择名称包含所需值之间的日期的表?

  • 查询数据字典(在 Oracle 中为 user_tables
  • 提取他们名字的DATE部分(我选择了regexp_substr函数;你可以使用任何你认为合适的)
  • 将提取的子字符串转换为有效的日期值(使用TO_DATE函数)

因此:

SQL> select table_name
  2  from user_tables
  3  where table_name like 'USER_DETAILS%'
  4    and to_date(regexp_substr(table_name, '\d+$'), 'yyyymmdd')
  5        between date '2021-11-26' and date '2021-11-27';

TABLE_NAME
------------------------------
USER_DETAILS_20211126
USER_DETAILS_20211127

好的; 26.11.2021 和 27.11.2021 之间的两个表(我不想创建更多)。


工作的第二部分是从这些表中实际获取数据。这是一个接受日期周期作为参数并返回参考光标的函数(当然,您可以选择其他内容)。在代码中读取 cmets:

SQL> create or replace function f_test(par_date_from in date,
  2                                    par_date_to   in date)
  3    return sys_refcursor
  4  is
  5    l_str varchar2(1000);  -- contains the whole SELECT statement
  6    rc    sys_refcursor;
  7  begin
  8    -- loop through all tables whose names satisfy the condition
  9    for cur_r in
 10    (select table_name
 11     from user_tables
 12     where table_name like 'USER_DETAILS%'
 13       and to_date(regexp_substr(table_name, '\d+$'), 'yyyymmdd')
 14           between par_date_from and par_date_to
 15    ) loop
 16      -- compose a SELECT statement
 17      l_str := l_str ||
 18        'select ename, job, datum from ' || cur_r.table_name || ' union all ';
 19    end loop;
 20
 21    -- remove trailing UNION ALL
 22    l_str := rtrim(l_str, ' union all');
 23
 24    -- open and return ref cursor
 25    open rc for l_str;
 26    return rc;
 27  end;
 28  /

Function created.

好的,我们试试吧:

SQL> select f_test(date '2021-11-26', date '2021-11-27') from dual;

F_TEST(DATE'2021-11-
--------------------
CURSOR STATEMENT : 1

CURSOR STATEMENT : 1

ENAME      JOB       DATUM
---------- --------- ----------
SMITH      CLERK     26.11.2021
JONES      MANAGER   26.11.2021
SCOTT      ANALYST   26.11.2021
ADAMS      CLERK     26.11.2021
FORD       ANALYST   26.11.2021
ALLEN      SALESMAN  27.11.2021
WARD       SALESMAN  27.11.2021
MARTIN     SALESMAN  27.11.2021
BLAKE      MANAGER   27.11.2021
TURNER     SALESMAN  27.11.2021
JAMES      CLERK     27.11.2021

11 rows selected.


SQL>

它对我有用;我希望你根本不需要让它“工作”,但是 - 在你应用我们已经建议的内容之后 - 运行一个简单的

SQL> select * from user_details
  2  where datum between date '2021-11-26' and date '2021-11-27';

    DEPTNO      EMPNO ENAME      JOB       DATUM
---------- ---------- ---------- --------- ----------
        20       7369 SMITH      CLERK     26.11.2021
        20       7566 JONES      MANAGER   26.11.2021
        20       7788 SCOTT      ANALYST   26.11.2021
        20       7876 ADAMS      CLERK     26.11.2021
        20       7902 FORD       ANALYST   26.11.2021
        30       7499 ALLEN      SALESMAN  27.11.2021
        30       7521 WARD       SALESMAN  27.11.2021
        30       7654 MARTIN     SALESMAN  27.11.2021
        30       7698 BLAKE      MANAGER   27.11.2021
        30       7844 TURNER     SALESMAN  27.11.2021
        30       7900 JAMES      CLERK     27.11.2021

11 rows selected.

SQL>

显然,我的user_details 表包含DATE 数据类型列,这使得一切很多都更简单了。

【讨论】:

  • 非常感谢。这确实解决了我的问题。
猜你喜欢
  • 2021-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-02
  • 2012-02-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多