# #postgresql #google-bigquery
Вопрос:
У меня есть таблица, в которой есть столбец массива с кучей идентификаторов породы собак. Я хочу найти эти значения и в основном возвращать значения поиска вместо идентификаторов guid.
CREATE TABLE dogs(
name text,
breeds text[]
);
INSERT INTO dogs (name, breeds) VALUES ('Barkley', '{"abc", "xyz"}');
INSERT INTO dogs (name, breeds) VALUES ('Ponyo', '{"zzz", "xyz"}');
CREATE TABLE breeds(
guid text,
breed text
);
INSERT INTO breeds (guid, breed) VALUES ('abc', 'Maltipoo');
INSERT INTO breeds (guid, breed) VALUES ('xyz', 'Jack Russel');
INSERT INTO breeds (guid, breed) VALUES ('zzz', 'Dalmatian');
Я хотел бы иметь возможность вернуть следующее:
Barkley, ['Maltipoo', 'Jack Russel']
Ponyo, ['Jack Russel', 'Dalmatian']
По сути, посмотрите их в моей таблице «породы», прежде чем возвращать значения.
Комментарии:
1. итак, BigQuery или Postgresql? поясните, пожалуйста
2. BigQuery, но обычно материал Postgres работает с BigQuery, поэтому я хотел бы посмотреть, как он решается на обеих платформах.
Ответ №1:
Злоупотребляя массивами таким образом, вам сначала нужно преобразовать их в наборы с помощью unnest()
.
SELECT d.name,
concat('[',
string_agg(concat('''',
b.breed,
''''),
', '),
']')
FROM dogs d
CROSS JOIN LATERAL unnest(d.breeds) db
(b)
LEFT JOIN breeds b
ON b.guid = db.b
GROUP BY d.name;
Но что вам действительно следует сделать, так это прекратить злоупотреблять массивами и нормализовать схему с помощью таблицы ссылок.
CREATE TABLE dogs
(name text,
PRIMARY KEY (name));
CREATE TABLE breeds
(guid text,
breed text,
PRIMARY KEY (guid));
CREATE TABLE dogs_breeds
(dog text,
breed text,
PRIMARY KEY (dog,
breed),
FOREIGN KEY (dog)
REFERENCES dogs
(name),
FOREIGN KEY (breed)
REFERENCES breeds
(guid));
INSERT INTO dogs
(name)
VALUES ('Barkley'),
('Ponyo');
INSERT INTO breeds
(guid,
breed) VALUES ('abc',
'Maltipoo'),
('xyz',
'Jack Russel'),
('zzz',
'Dalmatian');
INSERT INTO dogs_breeds
(dog,
breed)
VALUES ('Barkley',
'abc'),
('Barkley',
'xyz'),
('Ponyo',
'zzz'),
('Ponyo',
'xyz');
Таким образом, вы можете объявить ограничения внешнего ключа и обеспечить ссылочную целостность.
Затем вы можете просто присоединиться и объединить, чтобы получить свой результат.
SELECT d.name,
concat('[',
string_agg(concat('''',
b.breed,
''''),
', '),
']')
FROM dogs d
LEFT JOIN dogs_breeds db
ON db.dog = d.name
LEFT JOIN breeds b
ON b.guid = db.breed
GROUP BY d.name;
Ответ №2:
Ниже приведен стандартный SQL для BigQuery
select name, array(
select breed from t.breeds guid
join breeds using(guid)
) breeds
from dogs t
Если обратиться к образцам данных в вашем вопросе:
Комментарии:
1. вы пробовали? работает ли это на вас? если это так, подумайте, по крайней мере, о том, чтобы проголосовать за ответ!