#sql #database #google-bigquery #relational-database #data-warehouse
#sql #База данных #google-bigquery #реляционная база данных #хранилище данных
Вопрос:
Давайте предположим, что у меня есть 3 столбца в таблице со значениями, подобными этому:
table_1:
A | B | C
-----------------------
'xx' | '' | 'y'
'x' | 'y' | 'x'
'x' | 'x' | 'y'
'x' | 'yy' | ''
'x' | '' | 'yy'
'x' | 'y' | 'y'
У меня есть результирующий набор (результат оператора SQL SELECT), который я хочу идентифицировать в приведенной выше таблице, если он там существует:
[
('x', 'x', 'y')
('x', 'y', 'y')
]
Этот результирующий набор будет соответствовать 5 (из 6) строкам вместо 2 из приведенной выше таблицы, если я сравнил результаты простого объединения строк, например, я бы просто сравнил результаты этого: SELECT concat(A, B, C) FROM table_1
Я мог бы решить эту проблему, сравнив результаты более сложных функций конкатенации строк, подобных этой: SELECT concat('A=', A, '_', 'B=', B, '_', 'C=', C )
НО:
- Я не хочу использовать какой-либо жестко заданный специальный разделитель в конкатенации строк, такой как
_
или=
- потому что в данных может быть любой символ
- например: где-то в столбце B может быть это значение:
xx_C=yy
- например: где-то в столбце B может быть это значение:
- это не чистое решение
- потому что в данных может быть любой символ
- Я вообще не хочу использовать конкатенацию строк, потому что это уродливое решение
- это приводит к исчезновению «расстояния» между атрибутами
- недостаточно общий
- возможно, у меня есть столбцы с разными типами данных, которые я не хочу преобразовывать в столбец на основе СТРОК
Вопрос:
Можно ли как-то решить эту проблему без использования конкатенации строк? Есть ли простое решение для этой проблемы проверки значений из нескольких столбцов?
Я хочу решить это в BiqQuery, но меня интересует общее решение для каждой реляционной базы данных / хранилища данных.
Спасибо!
CREATE TABLE test.table_1 (
A STRING,
B STRING,
C STRING
) AS
SELECT * FROM (
SELECT 'xx', '', 'y'
UNION ALL
SELECT 'x', 'y', 'x'
UNION ALL
SELECT 'x', 'x', 'y'
UNION ALL
SELECT 'x', 'yy', ''
UNION ALL
SELECT 'x', '', 'yy'
UNION ALL
SELECT 'x', 'y', 'y'
)
SELECT A, B, C
FROM test.table_1
WHERE (A, B, C) IN ( -> I need this functionality
SELECT 'x', 'x', 'y'
UNION ALL
SELECT 'x', 'y', 'y'
);
Ответ №1:
Ниже приведен наиболее общий способ, который я могу придумать (стандартный SQL BigQuery):
#standardSQL
SELECT *
FROM `project.test.table1` t
WHERE t IN (
SELECT t
FROM `project.test.table2` t
)
Вы можете протестировать, поиграть с приведенным выше примером данных из вашего вопроса, как в примере ниже
#standardSQL
WITH `project.test.table1` AS (
SELECT 'xx' a, '' b, 'y' c UNION ALL
SELECT 'x', 'y', 'x' UNION ALL
SELECT 'x', 'x', 'y' UNION ALL
SELECT 'x', 'yy', '' UNION ALL
SELECT 'x', '', 'yy' UNION ALL
SELECT 'x', 'y', 'y'
), `project.test.table2` AS (
SELECT 'x' a, 'x' b, 'y' c UNION ALL
SELECT 'x', 'y', 'y'
)
SELECT *
FROM `project.test.table1` t
WHERE t IN (
SELECT t
FROM `project.test.table2` t
)
с выводом
Row a b c
1 x x y
2 x y y
Комментарии:
1. Это очень хороший подход, но я тестировал с BigQuery, и он работает не так, как ожидалось, при использовании других типов столбцов, кроме STRING. Я тестировал с идентификаторами на основе INT64. То же решение работает с таблицами, содержащими только столбцы на основе строк.
Ответ №2:
Используйте join
:
SELECT t1.*
FROM test.table_1 t1 JOIN
(SELECT 'x' as a, 'x' as b, 'y' as c
UNION ALL
SELECT 'x', 'y', 'y'
) t2
USING (a, b, c);