我不知道如何解决这个问题:
我们从各种在线供应商(亚马逊,Newegg等)导入订单信息。每个供应商都有自己的特定术语和结构,用于我们已镜像到数据库中的订单。我们的数据导入数据库没有任何问题,但我遇到的问题是编写一个方法,从数据库中提取必需的字段,而不管架构如何。
例如假设我们有以下结构:
Newegg结构:
"OrderNumber" integer NOT NULL, -- The Order Number
"InvoiceNumber" integer, -- The invoice number
"OrderDate" timestamp without time zone, -- Create date.
亚马逊结构:
"amazonOrderId" character varying(25) NOT NULL, -- Amazon's unique, displayable identifier for an order.
"merchant-order-id" integer DEFAULT 0, -- A unique identifier optionally supplied for the order by the Merchant.
"purchase-date" timestamp with time zone, -- The date the order was placed.
如何选择这些项目并将它们放入临时表格中供我查询?
临时表可能如下所示:
"OrderNumber" character varying(25) NOT NULL,
"TransactionId" integer,
"PurchaseDate" timestamp with time zone
据我所知,有些数据库代表一个带整数的订单号,而其他数据库则代表一个字符变化;处理我计划将数据类型转换为String值。
有没有人建议我阅读有关这方面的建议?
我不需要一个确切的答案,只需要朝着正确的方向轻推。
数据将由Java使用,因此如果任何特定的Java类有帮助,请随时提出建议。
答案 0 :(得分:3)
首先,您可以创建VIEW
来提供此功能:
CREATE VIEW orders AS
SELECT '1'::int AS source -- or any other tag to identify source
,"OrderNumber"::text AS order_nr
,"InvoiceNumber" AS tansaction_id -- no cast .. is int already
,"OrderDate" AT TIME ZONE 'UTC' AS purchase_date -- !! see explanation
FROM tbl_newegg
UNION ALL -- not UNION!
SELECT 2
"amazonOrderId"
,"merchant-order-id"
,"purchase-date"
FROM tbl_amazon;
您可以像查看任何其他表一样查询此视图:
SELECT * FROM orders WHERE order_nr = 123 AND source = 2;
如果source
不唯一,则order_nr
是必需的。您如何保证不同来源的唯一订单号?
timestamp without time zone
在全球范围内是不明确的。它与时区有关。如果您混合timestamp
和timestamptz
,则需要将timestamp
放置在具有AT TIME ZONE
构造的特定时区以使其正常工作。有关详细说明,请阅读this related answer。
我使用UTC作为时区,您可能想要提供另一个。简单的演员"OrderDate"::timestamptz
将假定您当前的时区。 AT TIME ZONE
已应用于timestamp
会导致timestamptz
。这就是为什么我没有添加另一个演员。
虽然可以,但我建议不要在PostgreSQL 中使用驼峰式标识符。避免多种可能的混淆。请注意我提供的小写标识符(没有现在不必要的双引号)。
请勿使用varchar(25)
作为order_nr
的类型。如果它必须是一个字符串,只需使用text
没有任意长度修饰符。如果所有订单号仅由数字组成,则integer
或bigint
会更快。
实现此目标的一种方法是实现视图。即,将结果写入(临时)表:
CREATE TEMP TABLE tmp_orders AS
SELECT * FROM orders;
ANALYZE tmp_orders; -- temp tables are not auto-analyzed!
ALTER TABLE tmp_orders
ADD constraint orders_pk PRIMARY KEY (order_nr, source);
您需要索引。在我的示例中,主键约束自动提供索引。
如果你的表很大,请确保你有足够的临时缓冲区来在中创建临时表之前在RAM 中处理它。否则它实际上会减慢你的速度。
SET temp_buffers = 1000MB;
必须是会话中对临时对象的第一次调用。不要在全局范围内设置它,仅适用于您的会话。无论如何,临时表会在会话结束时自动删除。
要估计您需要多少RAM,请创建一次表并测量:
SELECT pg_size_pretty(pg_total_relation_size('tmp_orders'));
有关此related question on dba.SE下的对象尺寸的更多信息。
如果您必须在一个会话中处理大量查询,则只需支付所有开销。对于其他用例,还有其他解决方案。如果您在查询时知道源表,那么将查询定向到源表会快得多。如果你不这样做,我会再次质疑你order_nr
的独特性。事实上,如果确保它是唯一的,您可以删除我介绍的source
列。
对于一个或几个查询,使用视图而不是物化视图可能会更快。
我还会考虑一个 plpgsql函数,它会一个接一个地查询一个表,直到找到记录。考虑到开销,考虑几个查询可能会更便宜。当然需要每个表的索引。
另外,如果您坚持使用text
或varchar
代替order_nr
,请考虑COLLATE "C"
。
答案 1 :(得分:0)
听起来你需要创建一个抽象类来定义与数据交互的基础知识,然后根据需要访问的每个数据库模式派生一个类。这将允许核心代码在单个对象类型上运行,然后每个实现都可以以特定于该数据库模式的形式指定查询。
类似的东西:
public class Order
{
private String orderNumber;
private BigDecimal orderTotal;
... etc ...
}
public abstract class AbstractOrderInformation
{
public abstract ArrayList<Order> getOrders();
...
}
有一个Newegg班:
public class NeweggOrderInformation extends AbstractOrderInformation
{
public ArrayList<Order> getOrders() {
... do the work of getting the newegg order
}
...
}
然后您可以拥有任意数量的格式,当您需要信息时,您可以遍历所有实现并从每个实现获取订单。