oracle 表有几百万数据,我要 把日期那一列 修改为本年的随机一天 该怎么写存储过程啊

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle 表有几百万数据,我要 把日期那一列 修改为本年的随机一天 该怎么写存储过程啊相关的知识,希望对你有一定的参考价值。

DECLARE
v_id INT;
v_value DATE;
v_days_on_year INT;
-- 定义游标.
CURSOR c_test_main IS
SELECT id, value FROM test_main
FOR UPDATE;
BEGIN
-- 计算本年多少天
v_days_on_year := TRUNC( ADD_MONTHS(SYSDATE,12), 'YYYY' ) - TRUNC( SYSDATE, 'YYYY' );
-- 打开游标.
OPEN c_test_main;
-- 填充数据.
FETCH c_test_main INTO v_id, v_value;
-- 假如检索到了数据,才处理.
WHILE c_test_main%FOUND LOOP
-- 更新数据.
UPDATE
test_main
SET
value = TRUNC( SYSDATE, 'YYYY' ) + TRUNC(DBMS_RANDOM.VALUE(0, v_days_on_year-1))
WHERE
CURRENT OF c_test_main;
-- 填充下一条数据.
FETCH c_test_main INTO v_id, v_value;
END LOOP;
-- 关闭游标
CLOSE c_test_main;
END;
/

主要知识点:

1. TRUNC( SYSDATE, 'YYYY' ) 取本年第一天
2. TRUNC( ADD_MONTHS(SYSDATE,12), 'YYYY' ) 明年的第一天
3. DBMS_RANDOM.VALUE(0, v_days_on_year-1)) 获取一个 0 - 天数之间的 随机数

不过数据量几百万, 不知道是不是需要 中间 提交几次。
参考技术A 要说怎么写倒是容易,甚至不需要存储过程,一个update语句就能搞定,用随机数.
可能的问题是效率问题,几百W数据,不太确定要运行多久.
参考技术B 是一个语句可以搞定,如下:
update table set c_date = TO_DATE (TRUNC( DBMS_RANDOM.VALUE (TO_NUMBER (TO_CHAR (trunc(sysdate,'year'),'J')),
TO_NUMBER (TO_CHAR (add_months(trunc(sysdate,'yyyy'),12)-1, 'J'))) ),'J')
参考技术C 一个update能搞定么?随机函数能生成指定的日期数据么?
我觉得怎么也要自己先定义一个生成日期的函数。

在 Python 中将一列日期时间转换为纪元

【中文标题】在 Python 中将一列日期时间转换为纪元【英文标题】:Convert a column of datetimes to epoch in Python 【发布时间】:2016-06-08 09:25:08 【问题描述】:

我目前遇到了 Python 问题。我有一个 Pandas DataFrame,其中一列是一个带日期的字符串。 格式为:

“%Y-%m-%d %H:%m:00.000”。例如:“2011-04-24 01:30:00.000”

我需要将整列转换为整数。我试图运行这段代码,但它非常慢,而且我有几百万行。

    for i in range(calls.shape[0]):
        calls['dateint'][i] = int(time.mktime(time.strptime(calls.DATE[i], "%Y-%m-%d %H:%M:00.000")))

你们知道如何将整列转换为纪元时间吗?

提前致谢!

【问题讨论】:

【参考方案1】:

使用to_datetime 将字符串转换为datetime,然后减去日期时间1970-1-1 并调用dt.total_seconds()

In [2]:
import pandas as pd
import datetime as dt
df = pd.DataFrame('date':['2011-04-24 01:30:00.000'])
df

Out[2]:
                      date
0  2011-04-24 01:30:00.000

In [3]:
df['date'] = pd.to_datetime(df['date'])
df

Out[3]:
                 date
0 2011-04-24 01:30:00

In [6]:    
(df['date'] - dt.datetime(1970,1,1)).dt.total_seconds()

Out[6]:
0    1303608600
Name: date, dtype: float64

您可以看到将这个值转换回产生相同的时间:

In [8]:
pd.to_datetime(1303608600, unit='s')

Out[8]:
Timestamp('2011-04-24 01:30:00')

因此您可以添加新列或覆盖:

In [9]:
df['epoch'] = (df['date'] - dt.datetime(1970,1,1)).dt.total_seconds()
df

Out[9]:
                 date       epoch
0 2011-04-24 01:30:00  1303608600

编辑

@Jeff 建议的更好方法:

In [3]:
df['date'].astype('int64')//1e9

Out[3]:
0    1303608600
Name: date, dtype: float64

In [4]:
%timeit (df['date'] - dt.datetime(1970,1,1)).dt.total_seconds()
%timeit df['date'].astype('int64')//1e9

100 loops, best of 3: 1.72 ms per loop
1000 loops, best of 3: 275 µs per loop

您还可以看到它明显更快

【讨论】:

感谢您的回答!它工作得很好,而且比 for 循环快得多! df.date.astype('int64')//1e9,虽然有点模糊 @GandalfSaxe 这是datetime 属性来访问类似日期时间的属性 @GandalfSaxe 啊,这是datetime 模块的别名:import datetime as dt 将更新以明确这一点 Ed:您可能已经注意到了,但是有一个 Meta 帖子要感谢您的 100K 评论:Congratulations to EdChum for 100,000 close reviews!。恭喜,谢谢!【参考方案2】:

我知道这很旧,但我相信正确(也是最干净)的方法是下面的单行:

calls['DATE'].apply(lambda x: x.timestamp())

这假定calls['DATE']datetime64[ns] 类型。如果没有,请使用:

pd.to_datetime(calls['DATE'], format="%Y-%m-%d %H:%m:00.000")

说明

要获取pd.Timestamp 的纪元值(以秒为单位),请使用:

pd.Timestamp('20200101').timestamp()

这应该给你1577836800.0。如果需要,您可以转换为 int。它是浮点数的原因是因为任何亚秒级时间都将在小数部分。

为了完整起见,您还可以使用以下方法获取原始纪元值(以纳秒为单位):

pd.Timestamp('20200101').value

给出 1577836800000000000,这是上述日期的纪元。 .value 属性是自纪元以来的纳秒数,因此我们除以 1e6 得到毫秒。如果您希望以秒为单位的纪元作为第一次调用,请除以 1e9。

【讨论】:

【参考方案3】:

来自Pandas documentation 处理时间序列数据:

我们减去纪元(UTC 时间 1970 年 1 月 1 日午夜),然后除以“单位”(1 毫秒)。

# generate some timestamps
stamps = pd.date_range('2012-10-08 18:15:05', periods=4, freq='D')

# convert it to milliseconds from epoch
(stamps - pd.Timestamp("1970-01-01")) // pd.Timedelta('1ms')

这将以毫秒为单位给出纪元时间。

【讨论】:

【参考方案4】:

为了扩展 s5s 的答案,我认为代码可以进一步泛化以适应丢失的数据(例如,由 pd.NaT 表示)。在 Pandas 1.2.4 上测试,不适用于 Pandas

calls['DATE'].apply(lambda x: x.timestamp() if not pd.isna(x) else pd.NA).astype('Int64')

一些cmets:

pd.isna() 将捕获 pd.NaT

lambda 表达式将 pd.NaT 转换为 pd.NA,这将是缺失数据的新表示

最后,lambda 表达式的输出将是整数和 pd.NA 的混合,因此我们需要像 Int64 这样的 Pandas ExtensionDtype 来处理它

示例输出:

0            <NA>
1            <NA>
2            <NA>
3            <NA>
4            <NA>
          ...
865    1619136000
866    1619136000
          ...
Name: DATE, Length: 870, dtype: Int64

【讨论】:

以上是关于oracle 表有几百万数据,我要 把日期那一列 修改为本年的随机一天 该怎么写存储过程啊的主要内容,如果未能解决你的问题,请参考以下文章

为啥java导出excel 日期格式不显示时分秒

PL/SQ连接oracle,L 新建表的时候, virtual那一列是啥意思

SQL语句怎么对单个字段去重,并且要显示所有列

怎么样在excel中,隐藏我不需要的本年的日期

在 Python 中将一列日期时间转换为纪元

access数据库中怎么将输入的日期让他显示成星期?