Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

SQL-Abfrage

12 views
Skip to first unread message

Lothar Geyer

unread,
Jul 3, 2012, 2:25:54 PM7/3/12
to
Ich suche mal wieder eine "optimale" SQL-Abfrage (zumindest optimaler
als meine derzeitige Lᅵsung). Sollte mit Access und SQLserver laufen.

Gegeben eine Tabelle Kontakte:
- KontaktID (Long, PrimaryKey, Autowert)
- PersonID (Long)
- UserID (Long)
- DatTim (Date)
- TypID (Integer)
- Notiz (Text)

Viele User unterhalten sich mit vielen Personen. Fᅵr jeden Kontakt
werden Zeitpunkt, ein Typ und eine Notiz hinterlegt.

_Gelᅵscht_ werden sollen fᅵr eine bestimmte PersonID jeweils der jᅵngste
(=letzte) Kontakt mit einem User, wenn dieser Kontakt eine bestimmte
TypID hat.

Lothar Geyer

Peter Lange

unread,
Jul 4, 2012, 1:51:53 PM7/4/12
to
Am 03.07.2012 20:25, schrieb Lothar Geyer:
> Ich suche mal wieder eine "optimale" SQL-Abfrage (zumindest optimaler
> als meine derzeitige Lösung). Sollte mit Access und SQLserver laufen.
>
> Gegeben eine Tabelle Kontakte:
> - KontaktID (Long, PrimaryKey, Autowert)
> - PersonID (Long)
> - UserID (Long)
> - DatTim (Date)
> - TypID (Integer)
> - Notiz (Text)
>
> Viele User unterhalten sich mit vielen Personen. Für jeden Kontakt
> werden Zeitpunkt, ein Typ und eine Notiz hinterlegt.
>
> _Gelöscht_ werden sollen für eine bestimmte PersonID jeweils der jüngste
> (=letzte) Kontakt mit einem User, wenn dieser Kontakt eine bestimmte
> TypID hat.

Ungetestet, da kein SQL-Server hier:

DELETE FROM KONTAKTE WHERE PersonID = <id> AND TypID = <whatever> AND
DatTim = (SELECT MAX(DatTim) FROM KONTAKTE
WHERE PersonID = <id> AND TypID = <whatever>)

hth
Peter



Lothar Geyer

unread,
Jul 4, 2012, 2:17:49 PM7/4/12
to
Hallo Peter,

Danke. Ist ja simpl. Aber manchmal sieht man den Wald vor lauter Bäumen
nicht. Ich habe mit Group By, Distinct, Top 1 und allem möglichen
probiert - und dann aufgegeben.

Ausrede: war ja schon spät...

Lothar Geyer

Peter Schneider

unread,
Jul 4, 2012, 4:23:39 PM7/4/12
to
Am 03.07.2012 20:25, schrieb Lothar Geyer:
> Ich suche mal wieder eine "optimale" SQL-Abfrage (zumindest optimaler als
> meine derzeitige Lösung). Sollte mit Access und SQLserver laufen.
>
> Gegeben eine Tabelle Kontakte:
> - KontaktID (Long, PrimaryKey, Autowert)
> - PersonID (Long)
> - UserID (Long)
> - DatTim (Date)
> - TypID (Integer)
> - Notiz (Text)
>
> Viele User unterhalten sich mit vielen Personen. Für jeden Kontakt werden
> Zeitpunkt, ein Typ und eine Notiz hinterlegt.
>
> _Gelöscht_ werden sollen für eine bestimmte PersonID jeweils der jüngste
> (=letzte) Kontakt mit einem User, wenn dieser Kontakt eine bestimmte TypID hat.

Du schreibst "der jüngste (letzte) Kontakt". Aber das muß nicht eindeutig
sein, sondern kann mehrere Datensätze liefern/löschen, wenn zu dem jüngsten
vorhandenen Timestamp mehrere Kontakteinträge existieren. Ist das
gewollt/erlaubt? Wenn ja, gibt der Key das her? Oder wenn nicht, gibt es einen
Unique Key auf (PersonID, UserID, TypID, DatTim), der die von dir verbal
beschriebene/unterstellte Eindeutigkeit sicherstellt?

In einer relationalen DB sind die Keys das wichtigste, und wenn eine Tabelle
nur einen Surrogate PK (Sequence) hat, und keinen Business Key, ist das gleich
verdächtig, bzw. stinkt erstmal nach Designfehler.

"...the key, and nothing but the key..." ;-)

Gruß
Peter

--
Climb the mountain not to plant your flag, but to embrace the challenge,
enjoy the air and behold the view. Climb it so you can see the world,
not so the world can see you. -- David McCullough Jr.


Lothar Geyer

unread,
Jul 5, 2012, 6:07:50 AM7/5/12
to
Hallo Peter,

Am 04.07.2012 22:23, schrieb Peter Schneider:
> ...
> Du schreibst "der jᅵngste (letzte) Kontakt". Aber das muᅵ nicht
> eindeutig sein, sondern kann mehrere Datensᅵtze liefern/lᅵschen, wenn zu
> dem jᅵngsten vorhandenen Timestamp mehrere Kontakteintrᅵge existieren.
> Ist das gewollt/erlaubt? Wenn ja, gibt der Key das her? Oder wenn nicht,
> gibt es einen Unique Key auf (PersonID, UserID, TypID, DatTim), der die
> von dir verbal beschriebene/unterstellte Eindeutigkeit sicherstellt?

Die Wahrscheinlichkeit, dass eine Kontaktperson zur selben Zeit mehrere
Anruf erhᅵlt, ist gleich Null (herangezogen wird die Zeit, zu der TAPI
den Eingang eines Anrufes meldet), da wir uns ja auf der Seite des
Anrufers befinden.
Vielleicht noch etwas zum Hintergrund. Wenn kein Telefon-Kontakt
zustande kommt, schreibt die Anwendung einen Satz in die Kontakthistorie
mit einer bestimmten Typ-Angabe (in diesem Fall also "Versuchszᅵhler").
Bei mehreren erfolglosen Versuchen werden die Zeiten in den selben
Datensatz geschrieben. Wenn nun bei einer Kontaktperson das Kennzeichen
"ausgeschieden" gesetzt wird (die KP ist also nicht mehr bei der Firma
beschᅵftigt), sollen diese Datensᅵtze (und eben nur die letzten)
gelᅵscht werden. Dass die KP auch frᅵher meist nicht erreichbar war,
soll durchaus dokumentiert bleiben.

> In einer relationalen DB sind die Keys das wichtigste, und wenn eine
> Tabelle nur einen Surrogate PK (Sequence) hat, und keinen Business Key,
> ist das gleich verdᅵchtig, bzw. stinkt erstmal nach Designfehler.
>
> "...the key, and nothing but the key..." ;-)

Da stimmte ich Dir schon zu. Der Primary Key kᅵnnte hier auch ᅵber die
PersonenID, UserID und Zeit gehen. Da aber auf Datensᅵtze in der
Kontakthistorie Bezug genommen wird (z.B. steht in einem Rechnungssatz,
mit welchem Kontakt die Rechnung versandt wurde, oder in einem
Dokumenten-Satz, mit welchem Kontakt eine technische Zeichnung erhalten
wurde), ist es einfacher, eine KontaktID bei den Rechnungen, Dokumenten
usw. zu speichern, als die drei Felder eines solchen Keys. Da in der
Kontakthistorie alle Telefonate, E-Mails, Briefe, Faxe usw. hinterlegt
sind, besteht auch eine (wenn auch minimale) Chance, dass zu einem ganz
bestimmten Zeitpunkt von einer Kontaktperson eine E-Mail an einen
Benutzer versandt wird, der genau zu diesem Zeitpunkt versucht, die
Kontaktperson anzurufen.

Lothar Geyer

PS: Meine erste Anwendung mit einer relationalen Datenbank (vorher mit
Netzwerk- und hierarchischen Datenbanken) habe ich etwa 1983
geschrieben, ich weiᅵ also schon, was ich tue. Und ich kenne auch den
Unterschied zwischen einem Key und einem Index. ;-)

Lutz Donnerhacke

unread,
Jul 5, 2012, 6:26:41 AM7/5/12
to
* Lothar Geyer wrote:
> Die Wahrscheinlichkeit, dass eine Kontaktperson zur selben Zeit mehrere
> Anruf erhält, ist gleich Null (herangezogen wird die Zeit, zu der TAPI
> den Eingang eines Anrufes meldet), da wir uns ja auf der Seite des
> Anrufers befinden.

Dann bildet man das in der DB durch einen UNIQUE Constrain ab. Das hilft
gegen Doppeleintragungen aus Dummheit, Fehler, Backup, Vorsatz oder
ungenauen Uhren.

> Da stimmte ich Dir schon zu. Der Primary Key könnte hier auch über die
> PersonenID, UserID und Zeit gehen.

Dann mach's. Auch wenn es sinnvoller ist, einen künstlichen primary key
einzuführen und die Bedingung als Constraint zu formulieren.

> Da aber auf Datensätze in der
> Kontakthistorie Bezug genommen wird (z.B. steht in einem Rechnungssatz,
> mit welchem Kontakt die Rechnung versandt wurde, oder in einem
> Dokumenten-Satz, mit welchem Kontakt eine technische Zeichnung erhalten
> wurde), ist es einfacher, eine KontaktID bei den Rechnungen, Dokumenten
> usw. zu speichern, als die drei Felder eines solchen Keys.

Eben. Allerdings ist Rechnungswesen wieder anders. Mit dem Erstellen einer
Rechnung sind sämtliche Datensätze, die zu dieser Rechnung gehören zu
duplizieren, um nicht zwei verschiedene Rechnungen ausdrucken zu können. Das
Finanzamt mag es gar nicht, wenn z.B. nach Änderung des Mehrwertsteuersatzes
eine später ausgedruckte Mahnung andere Werte enthält als die Rechnung.

Lothar Geyer

unread,
Jul 5, 2012, 8:57:06 AM7/5/12
to
Hallo Lutz,

Am 05.07.2012 12:26, schrieb Lutz Donnerhacke:
> * Lothar Geyer wrote:
>> Die Wahrscheinlichkeit, dass eine Kontaktperson zur selben Zeit mehrere
>> Anruf erhält, ist gleich Null (herangezogen wird die Zeit, zu der TAPI
>> den Eingang eines Anrufes meldet), da wir uns ja auf der Seite des
>> Anrufers befinden.
>
> Dann bildet man das in der DB durch einen UNIQUE Constrain ab. Das hilft
> gegen Doppeleintragungen aus Dummheit, Fehler, Backup, Vorsatz oder
> ungenauen Uhren.

Du hast nicht genau gelesen (oder nicht vollständig durchgelesen):
"mehrere _Anrufe_ zur gleichen Zeit", in der Tabelle werden aber auch
E-Mails gespeichert. Damit ist also _nicht_ sicher, dass es bei einem
Unique Key nicht zu Problemen führen würde. Im Übrigen kann man in der
Tabelle der Kontakthistorie manuell Notizen einfügen, wo auch schon mal
doppelte Zeiten / Personen / User vorkommen können. Nicht aber bei der
Auswahl von Datensätzen, die ich in meinem ursprünglichen Posting
beschrieben hatte.

>> Da stimmte ich Dir schon zu. Der Primary Key könnte hier auch über die
>> PersonenID, UserID und Zeit gehen.
>
> Dann mach's. Auch wenn es sinnvoller ist, einen künstlichen primary key
> einzuführen und die Bedingung als Constraint zu formulieren.

Siehe oben.
Aber selbst wenn die genannten Möglichkeiten einen Unique Key zuließen,
würde ich es in diesem Falle nicht machen. Das bedeutet nämlich
Verschwendung von Speicherplatz (überall dort, wo auf einen Eintrag in
der Kontakthistorie Bezug genommen wird, sind dann nicht ein Long,
sondern mehrere Felder vorzusehen) und sicher auch Performanceverluste,
wenn auch vielleicht nicht unbedingt messbar (wehret den Anfängen). Auch
wenn die reine Theorie das vorschreibt: es gibt immer Ausnahmen, die
gerechtfertigt sind.

>> Da aber auf Datensätze in der
>> Kontakthistorie Bezug genommen wird (z.B. steht in einem Rechnungssatz,
>> mit welchem Kontakt die Rechnung versandt wurde, oder in einem
>> Dokumenten-Satz, mit welchem Kontakt eine technische Zeichnung erhalten
>> wurde), ist es einfacher, eine KontaktID bei den Rechnungen, Dokumenten
>> usw. zu speichern, als die drei Felder eines solchen Keys.
>
> Eben. Allerdings ist Rechnungswesen wieder anders. Mit dem Erstellen einer
> Rechnung sind sämtliche Datensätze, die zu dieser Rechnung gehören zu
> duplizieren, um nicht zwei verschiedene Rechnungen ausdrucken zu können. Das
> Finanzamt mag es gar nicht, wenn z.B. nach Änderung des Mehrwertsteuersatzes
> eine später ausgedruckte Mahnung andere Werte enthält als die Rechnung.

??
Irgendwas hast Du da falsch verstanden. Der Datensatz in der
Kontakthistorie gehört _nicht_ zur Rechnung. Im Kopfsatz der Rechnung
steht lediglich ein Verweis auf den Satz in der Kontakthistorie, der
Post-/E-Mail-Ausgang dokumentiert.

Was soll da dupliziert werden? Und was hat das mit der Mehrwertsteuer zu
tun? Ein Verweis auf die Mehrwertsteuer-Tabelle steht in den Positionen
der Rechnung und nicht im Kopfsatz der Rechnung. Schließlich kann jede
Rechnungsposition einen anderen Mehrwertsteuersatz haben.

Lothar Geyer
Message has been deleted

Lothar Geyer

unread,
Jul 7, 2012, 1:02:53 AM7/7/12
to
Hallo Stefan,

wenn das ein Single Field Primary wäre, würde ich das ja auch machen.

Es gilt aber auch: Grau ist alle Theorie. ;-)

Lothar Geyer

Am 07.07.2012 06:37, schrieb Stefan Ram:
> Peter Schneider <pschnei...@googlemail.com> writes:
>> In einer relationalen DB sind die Keys das wichtigste, und wenn eine Tabelle
>> nur einen Surrogate PK (Sequence) hat, und keinen Business Key, ist das gleich
>> verdächtig, bzw. stinkt erstmal nach Designfehler.
>
> »If your data has a clear "master" field or combination
> of fields, which can uniquely identify each row (such as
> customer name in a table of customers or ISBN for a
> table of books), it is tempting to use that as the
> primary key of the table. However, my advice is: don't
> do that, use a separate, numeric, artificial primary key
> instead.«
>
> http://www.justsoftwaresolutions.co.uk/database/database-tip-use-an-artificial-primary-key.html
>

Lothar Geyer

unread,
Jul 7, 2012, 1:09:13 AM7/7/12
to
Na, da habe ich mal zu schnell geschossen - genau darum ging es ja. Hab
das erst gemerkt, als ich den gesamten Artikel gelesen habe.

Aber mein Posting war nicht mehr zurückzuziehen ...

Lothar Geyer

Peter Schneider

unread,
Jul 7, 2012, 4:19:51 AM7/7/12
to
Hallo Stefan,

Am 07.07.2012 06:37, schrieb Stefan Ram:
> Peter Schneider <pschnei...@googlemail.com> writes:
>> In einer relationalen DB sind die Keys das wichtigste, und wenn eine Tabelle
>> nur einen Surrogate PK (Sequence) hat, und keinen Business Key, ist das gleich
>> verdächtig, bzw. stinkt erstmal nach Designfehler.
>
> »If your data has a clear "master" field or combination
> of fields, which can uniquely identify each row (such as
> customer name in a table of customers or ISBN for a
> table of books), it is tempting to use that as the
> primary key of the table. However, my advice is: don't
> do that, use a separate, numeric, artificial primary key
> instead.«
>
> http://www.justsoftwaresolutions.co.uk/database/database-tip-use-an-artificial-primary-key.html

Du hast den wichtigsten Satz weggelassen, denn der Absatz in dem Artikel geht
so weiter:

"You can still maintain the uniqueness of the master columns by applying a
unique index to those columns."

Und das wird oft nicht gemacht, als optional betrachtet, und das ist ein
schwerer Fehler. Besser ist es im übrigen, den Business Key als Unique
Constraint und nicht nur als Unique Index zu implementieren.

Lothar Geyer

unread,
Jul 7, 2012, 5:52:55 AM7/7/12
to
Hi,

Am 07.07.2012 10:19, schrieb Peter Schneider:
> ...
> "You can still maintain the uniqueness of the master columns by applying
> a unique index to those columns."
>
> Und das wird oft nicht gemacht, als optional betrachtet, und das ist ein
> schwerer Fehler. Besser ist es im übrigen, den Business Key als Unique
> Constraint und nicht nur als Unique Index zu implementieren.


und warum?

Zitat:
Unique Index and Unique Constraint are the same. They achieve same goal.
SQL Performance is same for both. ...Even though syntax are different
the effect is the same.
(http://blog.sqlauthority.com/2007/04/26/sql-server-difference-between-unique-index-vs-unique-constraint/)

Peter Schneider

unread,
Jul 7, 2012, 3:42:35 PM7/7/12
to
Nein.

Ein DB-System sollte möglichst "selbstdokumentierend" sein, soweit das möglich
ist, im Interesse der Kollegen, die vielleicht nach dir auf dem von dir
designten Datenmodell die Schemaevolution voran treiben müssen.

Dabei ist ein Constraint deutlicher, denn er dokumentiert: hier ist eine
Business Rule. Das ist wichtig, sehr wichtig.

Ein Index, ob unique oder nicht, ist nur ein technisches Mittel zur
Zugriffsoptimierung, um bestimmten Klassen von SQL Statements einen
performanteren physikalischen Zugriffspfad zu ermöglichen. Die Anforderungen
an die Indizierung mögen sich ändern, wenn sich die Nutzungsmuster einer
Applikation aufgrund von neuen oder geänderten Funktionen, oder aufgrund
gestiegener Datenvolumina oder anders verteilter Daten ändern.

Die Business Rules, von denen die Keys ein Bestandteil sind, sind meist
deutlich langlebiger.

Von diesen Überlegungen unabhängig ist hierbei, daß es natürlich technisch
eine gewisse Überschneidung gibt: Oracle z.B. verwendet unique Indexes, um
unique constraints zu implementieren und zu erzwingen. Aber im Data Dictionary
sieht man dann zwei Objekte: den Constraint und den Index, und man kann den
Index nicht so einfach droppen, solange der Constraint existiert, was
verdeutlicht daß die Business Rule der wichtige, entscheidende Bestandteil
hier ist.

Lothar Geyer

unread,
Jul 8, 2012, 12:53:10 AM7/8/12
to
Hallo Peter,

Am 07.07.2012 21:42, schrieb Peter Schneider:
> ...
>> Zitat:
>> Unique Index and Unique Constraint are the same. They achieve same
>> goal. SQL
>> Performance is same for both. ...Even though syntax are different the
>> effect
>> is the same.
>> (http://blog.sqlauthority.com/2007/04/26/sql-server-difference-between-unique-index-vs-unique-constraint/)
>>
>
> Nein.
>
> Ein DB-System sollte möglichst "selbstdokumentierend" sein, soweit das
> möglich ist, im Interesse der Kollegen, die vielleicht nach dir auf dem
> von dir designten Datenmodell die Schemaevolution voran treiben müssen.
>
> Dabei ist ein Constraint deutlicher, denn er dokumentiert: hier ist eine
> Business Rule. Das ist wichtig, sehr wichtig.

wir reden aneinander vorbei: es liegt hier keine Business Rule vor.

Nochmal: Es können in der Tabelle doppelte Werte für (Kontaktperson +
Benutzer + Zeitpunkt) vorkommen. Es können aber keine doppelten Werte
für die Untermenge vom Typ X vorkommen. Und darum ging es ja in Deinem
Posting vom 4.7..

Lothar Geyer
Message has been deleted

Lutz Donnerhacke

unread,
Jul 9, 2012, 6:17:28 AM7/9/12
to
* Lothar Geyer wrote:
> Nochmal: Es können in der Tabelle doppelte Werte für (Kontaktperson +
> Benutzer + Zeitpunkt) vorkommen. Es können aber keine doppelten Werte
> für die Untermenge vom Typ X vorkommen. Und darum ging es ja in Deinem
> Posting vom 4.7..

Da Du E-Mail nach Eingangszeitpunkt akzeptierst, sind auch dann doppelte
Werte möglich. Selbst ein noch noch freingranularer Zeittyp hilft da nicht.

Lothar Geyer

unread,
Jul 9, 2012, 10:29:27 AM7/9/12
to
Hallo Lutz
Wie kommst Du drauf, dass ich den Eingangszeitpunkt verwende? So wie
andere E-Mail-Clients verwende ich auch den Zeitpunkt, der im
Header-Field "Date" bzw. "Delivery-Date" steht.

Und mit der Untermenge X meinte ich die Datensätze, die Versuchszähler
beinhalten (siehe mein Posting vom 5.7., 12.07 Uhr). Und diese
Untermenge kann definitiv keine doppelten Werte enthalten.

Lothar Geyer

Peter Schneider

unread,
Jul 9, 2012, 4:14:15 PM7/9/12
to
Meine letzten Anmerkungen bezogen sich auf den von Dir zitierten Artikel, und
deine Frage "warum" man bei Vorliegen von mehreren Candidate Keys auch die
Secondary Keys mit einem Unique Constraint versehen sollte.
0 new messages