Допустим, у меня есть таблица клиентов:
CREATE TABLE customers (
customer_number INTEGER,
customer_name VARCHAR(...),
customer_address VARCHAR(...)
)
У этой таблицы нет первичного ключа. Однако customer_name
и customer_address
должны быть уникальными для любого заданного customer_number
.
В этой таблице нередко содержится много повторяющихся клиентов. Чтобы обойти это дублирование, используется следующий запрос для выделения только уникальных клиентов:
SELECT
DISTINCT customer_number, customer_name, customer_address
FROM customers
К счастью, таблица традиционно содержала точные данные. То есть никогда не было конфликтующих customer_name
или customer_address
ни для какого customer_number
. Однако предположим, что противоречивые данные все же попали в таблицу. Я хочу написать запрос, который завершится ошибкой, вместо того, чтобы возвращать несколько строк для рассматриваемого customer_number
.
Например, я безуспешно пытался выполнить этот запрос:
SELECT
customer_number, DISTINCT(customer_name, customer_address)
FROM customers
GROUP BY customer_number
Есть ли способ написать такой запрос с помощью стандартного SQL? Если нет, то есть ли решение в SQL-запросе Oracle?
РЕДАКТИРОВАТЬ. Причина странного запроса:
По правде говоря, этой таблицы клиентов на самом деле не существует (слава богу). Я создал его в надежде, что он будет достаточно ясным, чтобы продемонстрировать потребности запроса. Однако люди (к счастью) понимают, что необходимость в таком запросе - меньшая из моих проблем, основываясь на этом примере. Поэтому теперь я должен избавиться от некоторой абстракции и, надеюсь, восстановить свою репутацию за то, что предлагал такую мерзость стола ...
Я получаю плоский файл, содержащий счета (по одному в строке) от внешней системы. Я прочитал этот файл построчно, вставив его поля в эту таблицу:
CREATE TABLE unprocessed_invoices (
invoice_number INTEGER,
invoice_date DATE,
...
// other invoice columns
...
customer_number INTEGER,
customer_name VARCHAR(...),
customer_address VARCHAR(...)
)
Как видите, данные, поступающие из внешней системы, денормализованы. То есть внешняя система включает в себя как данные счета, так и связанные с ним данные клиента в одной строке. Возможно, что один и тот же клиент будет в нескольких счетах-фактурах, поэтому могут быть дублирующиеся данные клиента.
Система не может начать обработку счетов до тех пор, пока все клиенты не будут гарантированно зарегистрированы в системе. Следовательно, система должна идентифицировать уникальных клиентов и регистрировать их при необходимости. Вот почему мне нужен запрос: потому что я работал с денормализованными данными, которые я не мог контролировать.
SELECT
customer_number, DISTINCT(customer_name, customer_address)
FROM unprocessed_invoices
GROUP BY customer_number
Надеюсь, это поможет прояснить первоначальную цель вопроса.
РЕДАКТИРОВАТЬ: примеры хороших / плохих данных
Для пояснения: customer_name
и customer_address
должны быть уникальными только для определенного customer_number
.
customer_number | customer_name | customer_address
----------------------------------------------------
1 | 'Bob' | '123 Street'
1 | 'Bob' | '123 Street'
2 | 'Bob' | '123 Street'
2 | 'Bob' | '123 Street'
3 | 'Fred' | '456 Avenue'
3 | 'Fred' | '789 Crescent'
Первые две строки хороши, потому что это одинаковые customer_name
и customer_address
для customer_number
1.
Две средние строки хороши, потому что они одинаковые customer_name
и customer_address
для customer_number
2 (хотя в другом customer_number
такие же customer_name
и customer_address
).
Последние две строки недопустимы, потому что есть два разных customer_address
es для customer_number
3.
Запрос, который я ищу, завершится ошибкой, если будет выполнен для всех шести этих строк. Однако, если на самом деле существовали только первые четыре строки, представление должно вернуть:
customer_number | customer_name | customer_address
----------------------------------------------------
1 | 'Bob' | '123 Street'
2 | 'Bob' | '123 Street'
Надеюсь, это проясняет, что я имел в виду под "конфликтующими customer_name
и customer_address
". Они должны быть уникальными по customer_number
.
Я ценю тех, кто объясняет, как правильно импортировать данные из внешних систем. Фактически, я уже делаю большую часть этого. Я намеренно скрыл все подробности того, что я делаю, чтобы было легче сосредоточиться на рассматриваемом вопросе. Этот запрос не является единственной формой проверки. Я просто подумал, что это станет красивым завершающим штрихом (так сказать, последней защитой). Этот вопрос был просто разработан, чтобы исследовать возможности SQL. :)