Tout d'abord, vous pouvez créer une VIEW
pour fournir cette fonctionnalité :
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;
Vous pouvez interroger cette vue comme n'importe quelle autre table :
SELECT * FROM orders WHERE order_nr = 123 AND source = 2;
-
Le
source
est nécessaire si leorder_nr
n'est pas unique. Sinon, comment garantiriez-vous des numéros de commande uniques sur différentes sources ? -
Un
timestamp without time zone
est une ambiguïté dans un contexte global. Elle n'est bonne qu'en rapport avec son fuseau horaire. Si vous mélangeztimestamp
ettimestamptz
, vous devez placer letimestamp
à un certain fuseau horaire avec leAT TIME ZONE
construire pour que cela fonctionne. Pour plus d'explications, lisez cette réponse connexe .J'utilise UTC comme fuseau horaire, vous voudrez peut-être en fournir un autre. Un simple cast
"OrderDate"::timestamptz
assumerait votre fuseau horaire actuel.AT TIME ZONE
appliqué à untimestamp
résultats entimestamptz
. C'est pourquoi je n'ai pas ajouté d'autre distribution. -
Pendant que vous pouvez , je conseille de ne pas utiliser d'identificateurs en casse de chameau dans PostgreSQL jamais . Évite de nombreux types de confusion possible. Notez les identifiants en minuscules (sans les guillemets désormais inutiles) que j'ai fournis.
-
N'utilisez pas
varchar(25)
comme type pour leorder_nr
. Utilisez simplementtext
sans modificateur de longueur arbitraire s'il doit s'agir d'une chaîne. Si tous les numéros de commande sont composés exclusivement de chiffres,integer
oubigint
serait plus rapide.
Performances
Une façon de rendre cela rapide serait de matérialiser la vue. C'est-à-dire, écrivez le résultat dans une table (temporaire) :
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);
Vous avez besoin Un index. Dans mon exemple, la contrainte de clé primaire fournit l'index automatiquement.
Si vos tables sont volumineuses, assurez-vous d'avoir suffisamment de tampons temporaires pour gérer cela dans la RAM avant vous créez la table temporaire. Sinon, cela vous ralentira.
SET temp_buffers = 1000MB;
Doit être le premier appel aux objets temporaires dans votre session. Ne le réglez pas à un niveau élevé à l'échelle mondiale, juste pour votre session. Une table temporaire est supprimée automatiquement à la fin de votre session de toute façon.
Pour obtenir une estimation de la quantité de RAM dont vous avez besoin, créez le tableau une fois et mesurez :
SELECT pg_size_pretty(pg_total_relation_size('tmp_orders'));
Plus d'informations sur la taille des objets sous cette question connexe sur dba.SE .
Tous les frais généraux ne sont payés que si vous devez traiter un certain nombre de requêtes au cours d'une même session. Pour les autres cas d'utilisation, il existe d'autres solutions. Si vous connaissez la table source au moment de la requête, il serait beaucoup plus rapide de diriger votre requête vers la table source à la place. Si vous ne le faites pas, je remettrais en question l'unicité de votre order_nr
une fois de plus. S'il est, en fait, garanti d'être unique, vous pouvez supprimer la colonne source
J'ai présenté.
Pour une ou quelques requêtes seulement, il peut être plus rapide d'utiliser la vue au lieu de la vue matérialisée.
Je considérerais également une fonction plpgsql qui interroge une table après l'autre jusqu'à ce que l'enregistrement soit trouvé. Peut-être moins cher pour quelques requêtes, compte tenu des frais généraux. Index pour chaque table nécessaire bien sûr.
Aussi, si vous vous en tenez au text
ou varchar
pour votre order_nr
, considérez COLLATE "C"
pour cela.