【问题标题】:How to create incrementing columns?如何创建递增列?
【发布时间】:2025-12-10 09:10:01
【问题描述】:

我有这些列名的表。

Province/State
Country/Region
Lat
Long
1/22/20
1/23/20
1/24/20
1/25/20
...
...
3/21/20

我知道要创建前 4 列,但我不知道如何创建日期列并增加它。

如何一次实现这么多列?
谢谢!

感染

死亡

恢复

我创建的对象关系数据模型

问题 -: 提交适用于您的数据库架构的 Oracle 脚本。

【问题讨论】:

  • 你应该在不同的日子有不同的行。为每个列创建一列通常是一种反模式。
  • 假设这是第一天,即 2020 年 1 月 22 日。然后我必须为该列输入值,第二天我必须ALTER TABLE ADD COLUMN '1/23/20' 并向该列添加新值。这一定是模式,不是吗?我从你的评论中得到了这个想法
  • 不,您不会每天在表中添加另一列。那是疯狂。您为什么不解释一下您尝试实施的业务规则,我们会告诉您如何对其建模。
  • 关系表存储关系,它们不是电子表格。如果你被告知不是这样,那么他们会教彻底的恶作剧。如果没有,他们可能希望您完全进行这种转换。
  • 我也可以使用pivot 关键字来执行此操作吗?

标签: oracle sqlplus


【解决方案1】:

不要尝试每天创建一列;只需创建一个包含位置、日期和每个统计信息(即感染、恢复、死亡等)列的表,然后如果您需要在查询中对它们进行透视(或在任何中间层应用程序 [即 PHP, Java, .net] 用于访问数据库)。

类似:

CREATE TABLE Regions(
  id        VARCHAR2(6)
            CONSTRAINT regions__id__pk PRIMARY KEY,
  parent_id VARCHAR2(6)
            CONSTRAINT regions_parent__fk REFERENCES Regions ( id ),
  name      VARCHAR2(50)
            CONSTRAINT regions__name__nn NOT NULL
            CONSTRAINT regions__name__u UNIQUE,
  latitude  NUMBER
            CONSTRAINT regions__lat__nn NOT NULL,
  longitude NUMBER
            CONSTRAINT regions__long__nn NOT NULL,
  CONSTRAINT regions__id__chk CHECK (
       ( parent_id IS     NULL AND REGEXP_LIKE( id, '^[A-Z]{2}$' ) )
    OR ( parent_id IS NOT NULL AND REGEXP_LIKE( id, '^[A-Z]{2}-[A-Z0-9]{1,3}$' ) )
  )
);
COMMENT ON COLUMN Regions.id        IS 'ISO 3166-2 Alpha-2 Country Code or ISO 3166-2 Province Code';
COMMENT ON COLUMN Regions.name      IS 'ISO 3166-2 English Short Name.';
COMMENT ON COLUMN Regions.latitude  IS 'Latitude of the region''s main city.';
COMMENT ON COLUMN Regions.longitude IS 'Longitude of the region''s main city.';

CREATE TABLE Virus_Statistics(
  id        NUMBER(20,0)
            GENERATED ALWAYS AS IDENTITY
            CONSTRAINT virus_statistics__id__pk PRIMARY KEY,
  location  VARCHAR2(6)
            CONSTRAINT virus_statistics__loc__nn NOT NULL
            CONSTRAINT virus_statistics__loc__fk REFERENCES Regions ( id ),
  datetime  DATE
            CONSTRAINT virus_statistics__dt__nn NOT NULL
            CONSTRAINT virus_statistics__dt__chk CHECK ( datetime = TRUNC( datetime ) ),
  infected  NUMBER(10,0),
  recovered NUMBER(10,0),
  dead      NUMBER(10,0),
  CONSTRAINT virus_statistics__loc__dt__u UNIQUE ( location, datetime )
);

然后您可以输入您的数据。例如,区域将是:

INSERT INTO Regions ( id, parent_id, name, latitude, longitude )
SELECT 'TH',    NULL, 'Thailand',          15.00000,  101.00000 FROM DUAL UNION ALL
SELECT 'JP',    NULL, 'Japan',             36.00000,  138.00000 FROM DUAL UNION ALL
SELECT 'SG',    NULL, 'Singapore',          1.28333,  103.83333 FROM DUAL UNION ALL
SELECT 'NP',    NULL, 'Nepal',             28.16667,   84.25000 FROM DUAL UNION ALL
SELECT 'MY',    NULL, 'Malaysia',           2.50000,  112.50000 FROM DUAL UNION ALL
SELECT 'CA',    NULL, 'Canada',            45.42472, - 75.69500 FROM DUAL UNION ALL
SELECT 'CA-BC', 'CA', 'British Columbia',  48.40733, -123.32977 FROM DUAL;

前 3 列数据是:

INSERT INTO Virus_Statistics ( location, datetime, infected, recovered, dead )
SELECT 'TH',    DATE '2020-01-22', 2 AS i, 0 AS r, 0 AS d FROM DUAL UNION ALL
SELECT 'TH',    DATE '2020-01-23', 3, 0, 0 FROM DUAL UNION ALL
SELECT 'TH',    DATE '2020-01-24', 5, 0, 0 FROM DUAL UNION ALL
SELECT 'JP',    DATE '2020-01-22', 2, 0, 0 FROM DUAL UNION ALL
SELECT 'JP',    DATE '2020-01-23', 1, 0, 0 FROM DUAL UNION ALL
SELECT 'JP',    DATE '2020-01-24', 2, 0, 0 FROM DUAL UNION ALL
SELECT 'SG',    DATE '2020-01-22', 0, 0, 0 FROM DUAL UNION ALL
SELECT 'SG',    DATE '2020-01-23', 1, 0, 0 FROM DUAL UNION ALL
SELECT 'SG',    DATE '2020-01-24', 3, 0, 0 FROM DUAL UNION ALL
SELECT 'NP',    DATE '2020-01-22', 0, 0, 0 FROM DUAL UNION ALL
SELECT 'NP',    DATE '2020-01-23', 0, 0, 0 FROM DUAL UNION ALL
SELECT 'NP',    DATE '2020-01-24', 0, 0, 0 FROM DUAL UNION ALL
SELECT 'MY',    DATE '2020-01-22', 0, 0, 0 FROM DUAL UNION ALL
SELECT 'MY',    DATE '2020-01-23', 0, 0, 0 FROM DUAL UNION ALL
SELECT 'MY',    DATE '2020-01-24', 0, 0, 0 FROM DUAL UNION ALL
SELECT 'CA-BC', DATE '2020-01-22', 0, 0, 0 FROM DUAL UNION ALL
SELECT 'CA-BC', DATE '2020-01-23', 0, 0, 0 FROM DUAL UNION ALL
SELECT 'CA-BC', DATE '2020-01-24', 0, 0, 0 FROM DUAL;

如果您想将其输出为每天的列,请使用PIVOT:

SELECT *
FROM   (
  SELECT name,
         latitude,
         longitude,
         datetime,
         infected
  FROM   Virus_Statistics v
         INNER JOIN Regions r
         ON ( r.id = v.location )
)
PIVOT (
  MAX( infected )
  FOR datetime IN (
    DATE '2020-01-22' AS "2020-01-22",
    DATE '2020-01-23' AS "2020-01-23",
    DATE '2020-01-24' AS "2020-01-24"
  )
)

哪些输出:

姓名 |纬度 |经度 | 2020-01-22 | 2020-01-23 | 2020-01-24 :--------------- | --------: | ---------: | ---------: | ---------: | ---------: 日本 | 36 | 138 | 2 | 1 | 2 马来西亚 | 2.5 | 112.5 | 0 | 0 | 0 新加坡 | 1.28333 | 103.83333 | 0 | 1 | 3 尼泊尔 | 28.16667 | 84.25 | 0 | 0 | 0 不列颠哥伦比亚 | 48.40733 | -123.32977 | 0 | 0 | 0 泰国 | 15 | 101 | 2 | 3 | 5

db小提琴here

【讨论】:

  • 现在也许您可以向 OP 解释他如何从他在问题中发布的图像的 Excel 电子表格中的数据填充这些数据库表 :-)