SQL日期转换

时间:2018-12-20 14:47:33

标签: sql oracle date sql-insert transformation

我已经在Excel中接收到数据,并且DATE列(名为ALL_PERIODS)为STRING,其格式为:

  

JFM 14-W / E 14/05/04

2014年1月,2月,2014年4月4日,周末

我需要将此列划分为三个新列:DATE_(DATE),YEAR_(INT),QUARTER_(INT),因此我编写了以下转换:

DATE列:

ALTER TABLE MY_TABLE 
   ADD DATE_TEMP VARCHAR2 (128);
UPDATE MY_TABLE 
   SET DATE_TEMP = SUBSTR(ALL_PERIODS, -2, 2);
UPDATE MY_TABLE 
   SET DATE_TEMP = REPLACE(DATE_TEMP, '/',  '');
UPDATE MY_TABLE 
   SET DATE_TEMP = to_char(to_date(DATE_TEMP, 'mmddyyyy'), 'yyyy-mm-dd');
UPDATE MY_TABLE 
   SET DATE_TEMP = REPLACE(DATE_TEMP, '00',  '20');
UPDATE MY_TABLE 
   SET DATE_TEMP = TO_DATE(DATE_TEMP, 'YYYY-MM-DD');
ALTER TABLE MY_TABLE 
ADD DATE_ DATE;
UPDATE MY_TABLE 
   SET DATE_ = DATE_TEMP;
ALTER TABLE MY_TABLE 
   DROP COLUMN DATE_TEMP;

YEAR列:

ALTER TABLE MY_TABLE
    ADD YEAR_TEMP VARCHAR2(128 BYTE);
UPDATE MY_TABLE
    SET YEAR_TEMP =  SUBSTR(ALL_PERIODS, 8, 4);
ALTER TABLE MY_TABLE
    ADD YEAR_ NUMBER(4);
UPDATE MY_TABLE
    SET YEAR_ =  YEAR_TEMP;
UPDATE MY_TABLE
    SET YEAR_ = CONCAT('20', YEAR_);
ALTER TABLE MY_TABLE
    DROP COLUMN YEAR_TEMP;

列季度:

ALTER TABLE MY_TABLE 
    ADD QUARTER NUMBER(1);
UPDATE MY_TABLE
    SET QUARTER_ = 4
        WHERE DATE_ = '30-DEC-17';
...and the same with other 3 quarters

它以某种方式有效,但是我想它没有效果(我在SQL方面不是很高级,我还在学习),并且更新操作太慢,所以我想转换ALL_PERIODS列,同时将具有三个所需列的数据插入到新表中。

请告诉我,INSERT的外观如何? 谢谢 N

4 个答案:

答案 0 :(得分:0)

window.addEventListener('beforeinstallprompt', e => {
console.log('beforeinstallprompt Event fired');
});

答案 1 :(得分:0)

DDL语句(添加/删除列)缓慢且不必要。插入数据时,请勿更改表定义!

我将这样插入3列(用真正的ALL_PERIODS值替换我使用的日期字符串):

INSERT INTO MY_TABLE (DATE_, YEAR_, QUARTER_)
TO_DATE(SUBSTR('JFM 14 - W/E 04/05/14', -8), 'dd/mm/yy'),
EXTRACT(YEAR FROM TO_DATE(SUBSTR('JFM 14 - W/E 04/05/14', -2), 'yy')),
-- OR SHORTER IF ALWAYS IN THE 2000: TO_NUMBER(SUBSTR('JFM 14 - W/E 04/05/14', -2)) + 2000
DECODE(SUBSTR('JFM 14 - W/E 04/05/14',1,3), 'JFM', 1, 'AMJ', 2, 'JAS', 3, 'OND', 4);

致谢

答案 2 :(得分:0)

是否已将ALL_PERIODS加载到表中?
并且要计算的额外列已添加到表中?

然后1次更新就足够了。

UPDATE MY_TABLE
SET 
 DATE_ = TO_DATE(SUBSTR(RTRIM(ALL_PERIODS),-8),'MM/DD/YY')
,YEAR_ = 2000+SUBSTR(ALL_PERIODS,5,2)
,QUARTER_ = DECODE(SUBSTR(ALL_PERIODS,1,3), 'JFM', 1, 'AMJ', 2, 'JAS', 3, 'OND', 4)
WHERE ALL_PERIODS IS NOT NULL 
  AND DATE_ IS NULL

db <>小提琴here

上进行测试

答案 3 :(得分:0)

我首先简单地插入记录来模拟您的Excel日期字符串。您可以使用此逻辑来查看如何完成转换。

  

设置

INSERT INTO myTable (baseDate)
SELECT 'JFM 14 - W/E 04/05/14' FROM dual
UNION ALL 
SELECT 'AMJ 14 - W/E 06/05/14' FROM dual
UNION ALL 
SELECT 'JAS 14 - W/E 09/05/14' FROM dual
UNION ALL 
SELECT 'OND 14 - W/E 12/05/14' FROM dual
UNION ALL 
SELECT 'JFM 15 - W/E 04/05/15' FROM dual
UNION ALL 
SELECT 'AMJ 15 - W/E 06/05/14' FROM dual
UNION ALL 
SELECT 'JAS 15 - W/E 09/05/14' FROM dual
UNION ALL 
SELECT 'JAS 49 - W/E 03/05/49' FROM dual
UNION ALL 
SELECT 'JAS 50 - W/E 04/05/50' FROM dual
     

下一个SELECT行将验证服务器的默认日期格式。此值可能会影响字符串的日期解释。

SELECT value FROM v$nls_parameters WHERE parameter ='NLS_DATE_FORMAT';
| VALUE     |
| :-------- |
| DD-MON-RR |

在插入值之后,我可以基于该值更新表。

UPDATE myTable
SET
    DATE_ = 
        TO_DATE(
            SUBSTR(baseDate,INSTR(baseDate, ' ', -1)+1,8) -- Find last space to get end of string date value.
            , 'MM/DD/RR'
        )  /* TO_DATE already creates date object. RR mask rounds to 4-digit year. (49 = 1949, 50 = 2050) */
    , QUARTER_ = 
        CASE SUBSTR(baseDate, 1, 3)
            WHEN 'JFM' THEN 1 
            WHEN 'AMJ' THEN 2
            WHEN 'JAS' THEN 3
            WHEN 'OND' THEN 4
        END

对于DATE_,您不需要执行TO_CHAR,因为TO_DATE会将字符串转换为数据库中date列的日期值。您的数据库并不真正在乎日期是否看起来像'yyyy-mm-dd',因为它无论如何都不会那样看。我使用RR掩码将2位数字的年份值转换为4位数字的年份值。这会将49转换为2049,将50转换为1950。如果您不需要19xx日期,则可以使用YY。如果需要,可以对字符串值进行其他验证,以确保可以将其转换为日期。

对于QUARTER_,这只是一个简单的CASE语句,用于将四分之一字符串解释为数字。

然后,根据YEAR_中的日期值更新DATE_。这样可以确保我的年份在行中保持一致。如果从基本字符串中提取值,也可以在初始更新中完成。

UPDATE myTable
SET YEAR_ = EXTRACT ( YEAR FROM DATE_ )

这给我们:

BASEDATE              | DATE_     | YEAR_ | QUARTER_
:-------------------- | :-------- | ----: | -------:
JFM 14 - W/E 04/05/14 | 05-APR-14 |  2014 |        1
AMJ 14 - W/E 06/05/14 | 05-JUN-14 |  2014 |        2
JAS 14 - W/E 09/05/14 | 05-SEP-14 |  2014 |        3
OND 14 - W/E 12/05/14 | 05-DEC-14 |  2014 |        4
JFM 15 - W/E 04/05/15 | 05-APR-15 |  2015 |        1
AMJ 15 - W/E 06/05/14 | 05-JUN-14 |  2014 |        2
JAS 15 - W/E 09/05/14 | 05-SEP-14 |  2014 |        3
JAS 49 - W/E 03/05/49 | 05-MAR-49 |  2049 |        3
JAS 50 - W/E 04/05/50 | 05-APR-50 |  1950 |        3

由于DATE_是实际的日期对象,因此在显示时,您可以使用所需的任何蒙版对其进行格式化。

db <>提琴here