web-dev-qa-db-fra.com

Mise à jour avec la condition de jointure sur les mots correspondants dans les colonnes d'une autre table

J'ai 2 tables qui ressemblent à ceci:

Tableau A:

CREATE TEMP TABLE table_a (
  Column_1 text,
  ID_number int
);
INSERT INTO table_a VALUES
  ('foo,bar,baz', 123),
  ('qux,quux,quuz',456),
  ('corge,grault,garply',789),
  ('qux,bar,grault', 101);

Tableau B:

CREATE TEMP TABLE table_b (
  Column_1 text,
  Column_2 text,
  ID_number int
);
INSERT INTO table_b VALUES
  ('foo','baz',null),
  ('qux','quzz',null),
  ('corge','garply',null);

J'essaie de copier les valeurs de la colonne ID_Number dans le tableau A, où les valeurs de la colonne 1 et 2 du tableau B peuvent être trouvées dans la même ligne de la colonne 1 dans le tableau A.

C'est le genre de chose que je pensais à:

UPDATE table_b AS B 
SET id_number = A.id_number 
FROM table_a AS A 
WHERE A.column_1 LIKE B.column_1
  AND A.column_1 LIKE B.column_2

.. Mais évidemment cela ne fonctionne pas.

Comment puis-je traduire cela en une requête appropriée?

informations supplémentaires

table_a.Column_1 contient des adresses britanniques, par exemple:

'47 BOWERS PLACE, GREAT YARMOUTH, NORFOLK, NR20 4AN'

Dans table_b J'ai la première ligne de l'adresse dans Column_1 (alors, '47 BOWERS PLACE') et le code postal ('NR20 4AN') dans Column_2.

Je pensais qu'il serait préférable de simplifier les choses, mais peut-être que les données réelles ont une certaine pertinence dans cette situation.

table_a a environ 30 millions d'adresses. table_b a environ 60 000 rangées.

La performance est pertinente, plus cela fonctionne plus rapidement, et il sera probablement répété à l'avenir.

5
Matt

La clé ici est que Column_1, Représente trois valeurs possibles pour la jointure. Donc, ce que vous voulez utiliser est string_to_array() (Tant que ces valeurs sont séparées par des virgules et ne peuvent pas inclure elles-mêmes une virgule).

Exécutez cette requête,

SELECT id_number, string_to_array(column_1, ',') AS column_1
FROM table_a;
 id_number |       column_1        
-----------+-----------------------
       123 | {foo,bar,baz}
       456 | {qux,quux,quuz}
       789 | {corge,grault,garply}
       101 | {qux,bar,grault}

Maintenant, nous pouvons exécuter notre UPDATE utiliser = ANY() ,

UPDATE table_b
SET id_number = A.id_number
FROM (
  SELECT id_number, string_to_array(column_1, ',') AS column_1
  FROM table_a
) AS A
WHERE table_b.column_1 = ANY(A.column_1)
  AND table_b.column_2 = ANY(A.column_1);

Vous pouvez alternativement utiliser <@

WHERE ARRAY[table_b.column_1, table_b.column_2] <@ A.column_1;

Cela rend même un peu plus compact ..

UPDATE table_b
  SET id_number = A.id_number
FROM table_a AS A                              
  WHERE ARRAY[table_b.column_1, table_b.column_2] <@ string_to_array(A.column_1, ',');
6
Evan Carroll