Sicher Normalisierung der Daten über SQL-Abfrage

Angenommen ich habe eine Tabelle Kunden:

CREATE TABLE customers (
    customer_number  INTEGER,
    customer_name    VARCHAR(...),
    customer_address VARCHAR(...)
)

In dieser Tabelle keine nicht einen Primärschlüssel haben. Allerdings customer_name und customer_address sollte einzigartig für jede gegebene customer_number.

Es ist nicht ungewöhnlich für diese Tabelle enthalten viele doppelte Kunden. Um dies zu umgehen Vervielfältigung, die folgende Abfrage verwendet wird, zu isolieren, nur die eindeutige Kunden:

SELECT
  DISTINCT customer_number, customer_name, customer_address
FROM customers

Zum Glück, der Tisch hat traditionell enthalten genaue Daten. Das heißt, es hat nie eine entgegenstehende customer_name oder customer_address für alle customer_number. Jedoch, angenommen, widersprüchliche Daten habe es in die Tabelle ein. Ich möchte eine Abfrage schreiben, die scheitern wird, eher als die Rückkehr mehrere Zeilen für die customer_number in Frage stellen.

Beispielsweise, ich habe diese Abfrage mit Nein Erfolg:

SELECT
  customer_number, DISTINCT(customer_name, customer_address)
FROM customers
GROUP BY customer_number

Gibt es eine Möglichkeit zu schreiben, wie eine Abfrage mit SQL-standard? Wenn nicht, gibt es eine Lösung, die in Oracle-spezifische SQL?

EDIT: Die Gründe hinter dem bizarre-Abfrage:

Wahrheit gesagt werden, diese Kunden-Tabelle tatsächlich nicht vorhanden ist (Gott sei Dank). Ich habe es gehofft, es wäre klar genug, um zu zeigen, die Bedürfnisse der Abfrage. Jedoch, Menschen sind (zum Glück) fangen auf, dass die Notwendigkeit für eine solche Abfrage ist meine kleinste Sorge, basiert auf diesem Beispiel. Daher muss ich nun abziehen einige der Abstraktion und hoffentlich wieder meinen Ruf für die Annahme, eine solche Abscheulichkeit von einer Tabelle...

Erhalte ich eine flat-Datei mit Rechnungen (eine pro Zeile) aus einem externen system. Ich habe diese Datei Lesen, Zeile für Zeile, einfügen und die Felder in dieser Tabelle:

CREATE TABLE unprocessed_invoices (
    invoice_number   INTEGER,
    invoice_date     DATE,
    ...
    // other invoice columns
    ...
    customer_number  INTEGER,
    customer_name    VARCHAR(...),
    customer_address VARCHAR(...)
)

Wie Sie sehen können, werden die Daten für die Anreise aus dem externen system ist denormalisierten. Das heißt, das externe system umfasst sowohl die Rechnungs-Daten und Ihre zugeordneten Kunden-Daten auf der gleichen Linie. Es ist möglich, dass mehrere Rechnungen über die gleichen Kunden, daher ist es möglich, doppelte Kundendaten.

Kann das system nicht mit der Verarbeitung beginnen die Rechnungen, bis alle Kunden garantiert werden, die im system registriert. Deshalb muss das system identifizieren Sie die einzigartige Kunden und registrieren Sie Sie als notwendig. Dies ist der Grund, warum ich wollte die Abfrage: , weil ich arbeiten war mit denormalisierten Daten, die ich hatte keine Kontrolle über.

SELECT
  customer_number, DISTINCT(customer_name, customer_address)
FROM unprocessed_invoices
GROUP BY customer_number

Ich hoffe, dies hilft bei der Klärung der ursprünglichen Absicht der Frage.

EDIT: Beispiele für gute/schlechte Daten

Klären: customer_name und customer_address nur eindeutig sein für einen bestimmten 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'

Die ersten beiden Zeilen sind in Ordnung, da es das gleiche customer_name und customer_address für customer_number 1.

Den mittleren beiden Zeilen sind in Ordnung, da es das gleiche customer_name und customer_address für customer_number 2 (obwohl ein anderer customer_number hat die gleiche customer_name und customer_address).

Den letzten beiden Zeilen sind nicht okay, weil es zwei verschiedene customer_addresses für customer_number 3.

Die Abfrage, die ich bin auf der Suche nach scheitern würden, wenn gegen alle diese sechs Zeilen. Jedoch, wenn nur die ersten vier Zeilen, die eigentlich vorhanden sind, sollte die Ansicht zurück:

 customer_number | customer_name | customer_address
----------------------------------------------------
 1               | 'Bob'         | '123 Street'
 2               | 'Bob'         | '123 Street'

Ich hoffe das verdeutlicht, was ich mit "Konflikt customer_name und customer_address". Sie haben eindeutig pro customer_number.

Ich schätzen diejenigen, die erklären, wie man richtig importieren von Daten aus externen Systemen. In der Tat, ich bin schon dabei die meisten bereits. Ich absichtlich hid all die details von dem, was ich bin zu tun, so dass es einfacher wäre, den Fokus auf die Frage auf der hand. Diese Abfrage soll nicht die einzige form der überprüfung. Ich dachte nur es wäre ein nettes letzten Schliff (Letzte Verteidigung, so zu sprechen). Diese Frage war einfach konzipiert, um zu untersuchen, was nur möglich war, mit SQL. 🙂

  • Was meinst du mit "fail, anstelle der Rückgabe von mehreren Zeilen"? In der Regel, wenn ich denke, der eine sql-Abfrage fehlschlägt, bedeutet es, dass ich habe keine Zeilen, oder auch ein Produkt der Tabellen, ich bin bei. Ich dachte, Sie waren auf der Suche für ein select * from (select count(*) as cnt, kunden_nr, customer_name, customer_address From Kunden group by kunden_nr, customer_name, customer_address), wo die cnt - > 1 Art der Abfrage.
  • Von "fail", ich meinte das DBMS sollte einen Fehler zurückgeben, anstatt die Ergebnisse (wie bei der Abfrage einer nicht existierenden Tabelle). Ich verstehe, dass ich kann verwenden Sie die "SELECT COUNT(*) ... GROUP BY ... HAVING ..." - Abfrage zu ermitteln, die Anwesenheit von widersprüchlichen Daten, aber ich war einfach neugierig zu sehen, wenn Sie eine Abfrage ähnlich der, die ich beschrieben tatsächlich existierte. Danke für den Kommentar, aber! 🙂
InformationsquelleAutor Adam Paynter | 2009-06-12
Schreibe einen Kommentar