php-resource



Zurück   PHP-Scripte PHP-Tutorials PHP-Jobs und vieles mehr > Entwicklung > SQL / Datenbanken
 

Login

 
eingeloggt bleiben
star Jetzt registrieren   star Passwort vergessen
 

 

 


SQL / Datenbanken Probleme mit SQL? Hier könnt ihr eure Fragen zu SQL (MySQL, PostgreSQL, MS-SQL und andere ANSI-SQL Server) los werden.

Antwort
 
LinkBack Themen-Optionen Thema bewerten
  #1 (permalink)  
Alt 08-02-2010, 16:26
Dampfi
 Registrierter Benutzer
Links : Onlinestatus : Dampfi ist offline
Registriert seit: Jun 2006
Ort: Dresden
Beiträge: 59
Dampfi ist zur Zeit noch ein unbeschriebenes Blatt
Dampfi eine Nachricht über ICQ schicken
Question doppelte Datensätze mit unterschiedlicher WHERE-Bedingung?

Hallo Community,

ich stehe gerade sowas von auf dem Schlauch und hoffe dass mir hier geholfen werden kann...

Folgendes Problem:

Auf meine Stammdaten-SQL-Tabelle mache ich folgende Abfrage:
Code:
SELECT count( * ) AS c, id FROM stammdaten GROUP BY concat( vorname, nachname, strasse, wohnort)
HAVING c = 2 ORDER BY ID ASC
Diese Abfrage liefert mir die IDs aller User, dessen VORNAME, NACHNAME, STRASSE und WOHNORT gleich sind und die exakt zweimal in der Tabelle stehen. (Bsp.: Max Mustermann auf der Musterstraße in Musterstadt steht einmal mit ID 11 und einmal mit ID 22 in der Datenbank... => Query gibt 11 und 22 zurück).

Das funktioniert auch perfekt, ist allerdings noch nicht mein Endziel. Jetzt weiß ich zwar, dass der User doppelt in der DB steht, aber das reicht mir noch nicht!
Und zwar habe ich in der Tabelle noch ein Feld "STATUS". Um am Beispiel zu bleiben: Die ID 11 hat im Feld STATUS eine "0" stehen, die ID 22 hat einen STATUS von "1". Aktuell ist das Resultat des Query IMMER 11 und 22, ganz egal welchen Status der doppelte eingetragene User besitzt.
Nun möchte ich aber nur die ID, deren STATUS = 0 ist, in dem Falle also NUR die ID 11. Das führt mich zu folgendem Problem:

Füge ich dem Query (siehe oben) ein WHERE STATUS = 0 bzw. 1 hinzu, so bekomme ich auch nur ein Result, wenn BEIDE Datensätze STATUS 0 bzw. 1 besitzen.
Ich möchte aber, dass ich nur dann ein Result bekomme, wenn der eine STATUS = 0 und der andere STATUS = 1 ist. Ist bei beiden Datensätzen des Users der STATUS gleich (also bei beiden 0 oder bei beiden 1), dann möchte ich KEIN Result haben...

Wie muss ich jetzt die SQL-Abfrage erweitern, um das zu realisieren...?
Ich hoffe ich habe mich verständlich ausgedrückt, es ist nicht ganz einfach zu beschreiben

Ich würde mich über Lösungsvorschläge freuen, vielleicht gibt es ja noch eine alternativen Ansatz...

PS: Die einfachste Lösung wäre natürlich alle IDs in ein ARRAY zu nehmen und dieses dann durch eine foreach-Schleife zu jagen, um den Status abzufragen. Allerdings handelt es sich um ca. 20k Datensätze, die Perfomance von SQL-Abfragen in solchen Schleifen ist aber so langsam, dass dies für mich nicht in Frage kommt! Ich brauche das Result, ohne eine foreach-Schleife anzustrengen - und das geht ja dann nur über die SQL-Syntax oder irre mich da?

Geändert von Dampfi (08-02-2010 um 23:19 Uhr)
Mit Zitat antworten
  #2 (permalink)  
Alt 08-02-2010, 16:40
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Hallo,

dein Problem liegt in einem Missverständnis begründet. Deine Abfrage liefert dir nicht die IDs die doppelt sind, sondern jeweils eine beliebige ID aus einer Gruppe doppelter Datensätze.

Als Beispiel:

in der DB:
Code:
3, Max, Mustermann, Musterstadt
4, Berta, Beispiel, Irgendwo
5, Max, Mustermann, Musterstadt
6, jemand, anderes, nirgendwo
7, Berta, Beispiel, Irgendwo
im Abfrageergebnis:
Code:
2, 3
2, 7
oder

Code:
2, 5
2, 4
Welches davon du zurückbekommst, kannst du nicht vorab festlegen, aber ohne group_concat wählt MySQL eine beliebige ID aus der Gruppe aus und das kann beim Max die 3 oder die 5 und bei Berta die 4 oder die 7 sein.

Alle doppelten IDs pro Duplikatgruppe kannst du dir mit group_concat(id) in einer Spalte auflisten lassen.

Gruß,

Amica
__________________
Hast du die Grundlagen zur Fehlersuche gelesen? Hast du Code-Tags benutzt?
Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
Super, danke!
Mit Zitat antworten
  #3 (permalink)  
Alt 08-02-2010, 17:06
Dampfi
 Registrierter Benutzer
Links : Onlinestatus : Dampfi ist offline
Registriert seit: Jun 2006
Ort: Dresden
Beiträge: 59
Dampfi ist zur Zeit noch ein unbeschriebenes Blatt
Dampfi eine Nachricht über ICQ schicken
Standard

Zitat:
Zitat von AmicaNoctis Beitrag anzeigen
Hallo,

Als Beispiel:

in der DB:
Code:
3, Max, Mustermann, Musterstadt
4, Berta, Beispiel, Irgendwo
5, Max, Mustermann, Musterstadt
6, jemand, anderes, nirgendwo
7, Berta, Beispiel, Irgendwo
im Abfrageergebnis:
Code:
2, 3
2, 7
Danke erstmal für das schnelle Reply.
Allerdings liegt hier kein Missverständnis vor, denn ich möchte ja ALLE User erhalten, die doppelt da drin stehen. Also in deinem Beispiel ist das schon korrekt, dass ich einen Treffer auf Max Mustermann UND auf Berta Beispiel bekomme. So ist das schon gewollt.
Um mich an deinem Beispiel zu orientieren wünsche ich mir aber folgende Ausgabe:

in der DB:
Code:
3, Max, Mustermann, Musterstadt, 1
4, Berta, Beispiel, Irgendwo, 0
5, Max, Mustermann, Musterstadt, 0 
6, jemand, anderes, nirgendwo, 1
7, Berta, Beispiel, Irgendwo, 0 
(die angefügte Zahl ist mein Kriterium "Status")
im Abfrageergebnis:
Code:
2, 5
Mein Query findet die Dopplung, da VORNAME, NAME, STRASSE und ORT gleich sind. Wenn SQL einen solchen User findet, soll die Query gleich in einem Aufwasch mit prüfen, ob der Status gleich ist. Trifft dies zu, dann ist die Ausgabe unerwünscht. Ist bei beiden Datensätzen aber der Status verschieden (nämlich je ein betreffender Datensatz mit Status 0 und 1), dann wünsche ich eine Ausgabe der ID mit Status = 0...

Wie gesagt, vermutlich verfolge ich den falschen Ansatz, begriffen WARUM habe ich aber noch nicht... Oder bin ich hier wirklich dazu gezwungen eine Schleife zu erstellen und die IDs (die als Array vorliegen) da durchzujagen? Problem: Dann erreichen die User für ca. 3 Minuten die Seite nicht, denn solange läuft das Skript... Ist also nicht wirklich eine Lösung!

Danke aber schonmal dafür, dass du Dich mit dem Problem eines Fremden befasst
Mit Zitat antworten
  #4 (permalink)  
Alt 08-02-2010, 17:31
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Zitat:
Zitat von Dampfi Beitrag anzeigen
Mein Query findet die Dopplung, da VORNAME, NAME, STRASSE und ORT gleich sind. Wenn SQL einen solchen User findet, soll die Query gleich in einem Aufwasch mit prüfen, ob der Status gleich ist. Trifft dies zu, dann ist die Ausgabe unerwünscht. Ist bei beiden Datensätzen aber der Status verschieden (nämlich je ein betreffender Datensatz mit Status 0 und 1), dann wünsche ich eine Ausgabe der ID mit Status = 0...
Da musst du noch einen Self Join machen, in dem du prüfst, ob der Status verschieden ist.
__________________
Hast du die Grundlagen zur Fehlersuche gelesen? Hast du Code-Tags benutzt?
Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
Super, danke!
Mit Zitat antworten
  #5 (permalink)  
Alt 08-02-2010, 17:43
Dampfi
 Registrierter Benutzer
Links : Onlinestatus : Dampfi ist offline
Registriert seit: Jun 2006
Ort: Dresden
Beiträge: 59
Dampfi ist zur Zeit noch ein unbeschriebenes Blatt
Dampfi eine Nachricht über ICQ schicken
Standard

Self Join? Noch nie gehört
Werde das heute im Feierabend (der JETZT beginnt) mal recherchieren und morgen früh dann ausprobieren. Danke erstmal für deine Hilfe, zumindest habe ich dank Dir eine Spur

Es würde mich freuen, wenn du morgen im Laufe des Tages nochmal in den Thread schaust, denn bei mir taucht bestimmt noch die ein oder andere Frage zum Self-Join in Verbindung mit meinem urspünglichen Problem auf

Danke und sonnig-frostige Grüße aus Dresden
Dampfi
Mit Zitat antworten
  #6 (permalink)  
Alt 08-02-2010, 17:45
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Ich schaue bestimmt nochmal rein.

Dieselben Grüße zurück, auch aus Dresden
__________________
Hast du die Grundlagen zur Fehlersuche gelesen? Hast du Code-Tags benutzt?
Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
Super, danke!
Mit Zitat antworten
  #7 (permalink)  
Alt 08-02-2010, 20:58
EVAMasters
 Banned
Links : Onlinestatus : EVAMasters ist offline
Registriert seit: Jul 2009
Beiträge: 18
EVAMasters befindet sich auf einem aufstrebenden Ast
Standard sowas kommt von sowas

Grundsätzlich gilt:

SELECT <Aggregat>, <Schlüssel>
FROM <Tabelle> GROUP BY <Schlüssel>

Mit anderen Worten: Die Id hat hier in der Tat nix zu suchen.


Probier folgendes:

Zunächst liefert uns die Selektion

SELECT <Schlüssel>
FROM stammdaten
GROUP BY <Schlüssel>
HAVING COUNT(*) = 2

alle Kandidaten, die 2x in der Tabelle vorkommen. Offenbar interessieren uns nur jene, die sich im <Status> unterscheiden, deren Summe über <Status> also gleich 1 ist. Right?

SELECT <Schlüssel>
FROM stammdaten
GROUP BY <Schlüssel>
HAVING COUNT(*) = 2 AND SUM(Status) = 1

Der gewünschte Schlüssel für den Join mit <stammdaten> (um an die tatsächliche Id dran zu kommen) ist demnach:

SELECT 0 AS Status, <Schlüssel>
FROM stammdaten
GROUP BY <Schlüssel>
HAVING COUNT(*) = 2 AND SUM(Status) = 1



d.
Mit Zitat antworten
  #8 (permalink)  
Alt 08-02-2010, 22:59
Dampfi
 Registrierter Benutzer
Links : Onlinestatus : Dampfi ist offline
Registriert seit: Jun 2006
Ort: Dresden
Beiträge: 59
Dampfi ist zur Zeit noch ein unbeschriebenes Blatt
Dampfi eine Nachricht über ICQ schicken
Standard

Also ich habe die nötigen Dateien gerade nicht zur Hand, aber das erscheint mir logisch. Muss es natürlich ausprobieren, aber scheint als wäre das die schnellste und somit eleganteste Lösung für mein Problem...

Danke für dein Tutorial. Ich glaube ich sollte mich mehr mit SQL-Querys beschäftigen. Normal hol ich mir damit nur die Daten und regel den Rest über Arrays!
Mit Zitat antworten
  #9 (permalink)  
Alt 08-02-2010, 23:10
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Zitat:
Zitat von EVAMasters Beitrag anzeigen
Code:
SELECT 0 AS Status, <Schlüssel> 
   FROM stammdaten 
   GROUP BY <Schlüssel> 
   HAVING COUNT(*) = 2 AND SUM(Status) = 1
Zitat:
Zitat von Dampfi Beitrag anzeigen
aber das erscheint mir logisch
Mir nicht: select 0 as Status liefert immer 0, also wird die having-Bedingung sum(Status) = 1 nie erfüllt. Außerdem wollte Dampfi ja bei unterschiedlichen Statūs nur den Datensatz mit Status = 0. Ich behaupte immer noch, dass man dafür einen Self Join braucht.

Amica
__________________
Hast du die Grundlagen zur Fehlersuche gelesen? Hast du Code-Tags benutzt?
Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
Super, danke!
Mit Zitat antworten
  #10 (permalink)  
Alt 08-02-2010, 23:46
EVAMasters
 Banned
Links : Onlinestatus : EVAMasters ist offline
Registriert seit: Jul 2009
Beiträge: 18
EVAMasters befindet sich auf einem aufstrebenden Ast
Standard

SELECT 0 AS MyStatus

oder

einfach weglassen, was spielt das schon für eine Rolle für die Lösung?

tell me

Bedenke: 0 oder 1 ist durch den <Schlüssel> nicht spezifiziert. Was aber gilt:
<Schlüssel> und 0 liefert eindeutig eine Id x
<Schlüssel> und 1 liefert eindeutig eine Id y

Im Umkehrschluss heißt das: Wir wählen den Status (0 oder 1) einfach (!) selbst. Damit haben wir den gewünschten Datensatz eindeutig identifiziert.

d.
Mit Zitat antworten
  #11 (permalink)  
Alt 08-02-2010, 23:55
AmicaNoctis
  Moderatorin
Links : Onlinestatus : AmicaNoctis ist offline
Registriert seit: Jul 2009
Beiträge: 5.709
Blog-Einträge: 9
AmicaNoctis sorgt für eine eindrucksvolle AtmosphäreAmicaNoctis sorgt für eine eindrucksvolle Atmosphäre
Standard

Es spielt eine Rolle, weil kein Datensatz einer Gruppe zurückgegeben werden soll, wenn die gruppierten Datensätze den gleichen Status haben. Nur wenn er unterschiedlich ist, soll der Datensatz (oder dessen ID) zurückgegeben werden, der den Status 0 hat. Insofern kann man das eben nicht einfach selbst wählen, sondern muss erstmal die Datensätze mit der Übereinstimmung (<Schlüssel>) hinsichtlich ihrer Status-Felder vergleichen, um zu entscheiden, ob sie ins Ergebnis sollen und wenn ja, mit welchem Kandidaten.

Das lässt sich nun mal nicht mit group by realisieren, ohne eine Unterabfrage herzunehmen und da wäre es günstiger, mit einem Self Join zu arbeiten und ganz auf das group by zu verzichten.

Telling you!
__________________
Hast du die Grundlagen zur Fehlersuche gelesen? Hast du Code-Tags benutzt?
Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
Super, danke!
Mit Zitat antworten
  #12 (permalink)  
Alt 08-02-2010, 23:59
EVAMasters
 Banned
Links : Onlinestatus : EVAMasters ist offline
Registriert seit: Jul 2009
Beiträge: 18
EVAMasters befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von Dampfi Beitrag anzeigen
Normal hol ich mir damit nur die Daten und regel den Rest über Arrays!
... ich weiß genau was du meinst

Probleme kriegst du nur dann, wenn sich ein bestimmter Sachverhalt auch in PHP nicht ersichtlich oder nur schwer beschreiben lässt ...

Vielleicht erzähl ich ein wenig mehr zu diesem Thema auf dem <Usertreffen in Berlin>.

*join*

... probiers aus. Wenns nicht geht, geb ich dir nen Bier am 20sten aus, und ich werde die Angelegenheit nochmal überdenken.

Geändert von AmicaNoctis (09-02-2010 um 00:06 Uhr) Grund: Doppelpost
Mit Zitat antworten
  #13 (permalink)  
Alt 09-02-2010, 09:19
Dampfi
 Registrierter Benutzer
Links : Onlinestatus : Dampfi ist offline
Registriert seit: Jun 2006
Ort: Dresden
Beiträge: 59
Dampfi ist zur Zeit noch ein unbeschriebenes Blatt
Dampfi eine Nachricht über ICQ schicken
Standard

Sooo, ich habe mich heute morgen gleich voller Eifer ans Werk gemacht... und muss feststellen, dass EVAMasters Lösungs zwar logisch aussieht, mir als Resultat aber "LEER" z7urückgibt, und zwar in jeder Variation des Querys...

Ich muss zwar auf das Bier verzichten, da ich wohl nicht nach Berlin kommen werde, aber dem AmicaNoctis steht das doch viel eher zu

Ich versuchs jetzt mal per Self-Join!

EDIT:
Kommando (halb) zurück:
Code:
SELECT 0 AS Status, <Schlüssel> 
   FROM stammdaten 
   GROUP BY <Schlüssel> 
   HAVING COUNT(*) = 2 AND SUM(Status) = 1
Funktioniert doch... Hatte nur etwas vergessen im Query anzupassen ^^
Jetzt bekomme ich ein Result, jedoch sind da nach Stichprobenentnahme IDs mit drin, die den Status=1 besitzen... -.-

Geändert von Dampfi (09-02-2010 um 09:42 Uhr)
Mit Zitat antworten
  #14 (permalink)  
Alt 09-02-2010, 10:15
Dampfi
 Registrierter Benutzer
Links : Onlinestatus : Dampfi ist offline
Registriert seit: Jun 2006
Ort: Dresden
Beiträge: 59
Dampfi ist zur Zeit noch ein unbeschriebenes Blatt
Dampfi eine Nachricht über ICQ schicken
Standard

Die Endlösung, für die ich mich jetzt entschlossen habe:

Code:
SELECT STATUS , ID
FROM ma1_user_stammdaten
GROUP BY concat( vorname, nachname, strasse, wohnort ) 
HAVING COUNT( * )=2
AND SUM(STATUS)=1
Somit erhalt ich ein zweispaltiges Result in dieser Form:
Erster Datensatz:
[STATUS] = 0
[ID] = 234
Zweiter Datensatz:
[STATUS] = 1
[ID] = 257

Das Ganze frage ich mittels PHP ab, ob der Status 0 ist... Wenn ja => array_push. Dann habe ich alle User, die doppelt mit je einem Datensatz Status 0 bzw. 1 existieren abgegriffen und per PHP meine ID-Auswahl auf die Datensätze, die STATUS = 0 haben begrenzt...

Scheint gut zu funktionieren... Werde es dann gleichmal durch meine Testdatenbank jagen

Danke nochmal an alle Mitwirkenden für Eure Hilfe!
Mit Zitat antworten
  #15 (permalink)  
Alt 09-02-2010, 17:15
EVAMasters
 Banned
Links : Onlinestatus : EVAMasters ist offline
Registriert seit: Jul 2009
Beiträge: 18
EVAMasters befindet sich auf einem aufstrebenden Ast
Standard

na, na, na - entäusch mich ma nicht mit deiner Lösung - kurz vor dem Ziel.

Es fehlt doch nur noch:

Zitat:
Zitat von EVAMasters Beitrag anzeigen
Der gewünschte Schlüssel für den Join mit <stammdaten> (um an die tatsächliche Id dran zu kommen) ist demnach:
look:

SELECT b.* FROM (SELECT <Schlüssel> FROM stammdaten GROUP BY <Schlüssel> HAVING COUNT(*) = 2 AND SUM(Status) = 1) a, stammdaten b
WHERE a.<Schlüssel> = b.<Schlüssel> AND b.Status = 0

that's it

d.

ps: Amica kriegt das Bier, falls ich meine Lösung überdenken müsste
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
doppelte Datensätze unterbinden fritzje610 PHP Developer Forum 12 20-10-2008 13:13
Anzahl unterschiedlicher Datensätze (Timestamp) auslesen tsaenger SQL / Datenbanken 3 14-07-2006 14:42
[MSSQL] Doppelte Datensätze löschen spikis SQL / Datenbanken 3 01-10-2005 13:42
SELECT und doppelte Datensätze BobbyX SQL / Datenbanken 14 08-03-2003 02:31
Doppelte Datensätze löschen. AaM SQL / Datenbanken 2 24-09-2002 20:30

Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an


PHP News

ebiz-trader 7.5.0 mit PHP7 Unterstützung veröffentlicht
ebiz-trader 7.5.0 mit PHP7 Unterstützung veröffentlichtDie bekannte Marktplatzsoftware ebiz-trader ist in der Version 7.5.0 veröffentlicht worden.

28.05.2018 | Berni

Wissensbestand in Unternehmen
Wissensbestand in UnternehmenLebenslanges Lernen und Weiterbilden sichert Wissensbestand in Unternehmen

25.05.2018 | Berni


 

Aktuelle PHP Scripte

PHP Server Monitor

PHP Server Monitor ist ein Skript, das prüft, ob Ihre Websites und Server betriebsbereit sind.

11.09.2018 Berni | Kategorie: PHP/ Security
PHP WEB STATISTIK ansehen PHP WEB STATISTIK

Die PHP Web Statistik bietet Ihnen ein einfach zu konfigurierendes Script zur Aufzeichnung und grafischen und textuellen Auswertung der Besuchern Ihrer Webseite. Folgende zeitlichen Module sind verfügbar: Jahr, Monat, Tag, Wochentag, Stunde Folgende son

28.08.2018 phpwebstat | Kategorie: PHP/ Counter
Affilinator - Affilinet XML Produktlisten Skript

Die Affilinator Affilinet XML Edition ist ein vollautomatisches Skript zum einlesen und darstellen der Affili.net (Partnerprogramm Netzwerk) Produktlisten und Produktdaten. Im Grunde gibt der Webmaster seine Affilinet PartnerID ein und hat dann unmittelb

27.08.2018 freefrank@ | Kategorie: PHP/ Partnerprogramme
 Alle PHP Scripte anzeigen

Alle Zeitangaben in WEZ +2. Es ist jetzt 22:42 Uhr.