# Direkt aufeinander folgende Datensätze gruppieren und zählen



## Prengepower (16. Juni 2010)

Hallo!

Ich habe eine Datenbank die man sich wie folgt vorstellen könnte:

ID | Datum | Name

Dabei ist das Datum immer unterschiedlich.
Die ID kommt mehrfach vor. Das ist auch richtig so. Allerdings ist es falsch, dass teilweise eine Person direkt nacheinander die selbe ID "bearbeitet" hat..

Also könnte man es sich so vorstellen
ID | Datum | Name
1 1.1 A
1 2.1 A
1 2.1 B
2 1.1 A
3 2.1 C
4 2.1 A
4 2.1 C
4 4.1 A
5 5.1 B
5 7.1 B
6 2.1 A
6 3.1 B
6 3.1 C
7 5.1 A

Aussehen sollte es aber dann wie folgt:

ID | Datum | Name
1 1.1 A
1 2.1 B
2 1.1 A
3 2.1 C
4 2.1 A
4 2.1 C
4 4.1 A
5 5.1 B
6 2.1 A
6 3.1 B
6 3.1 C
7 5.1 A

Gibt es irgendwie einen SQL befehl mit dem ich das anstellen kann?!
Ich möchte das pro Name die Anzahl der Doppelten steht... Also welche mehrfach, nicht direkt aufeinander folgend, einer ID zugeordnet sind...
Sozusagen soll eine tabelle ausgegeben werden, wo ich den namen bekomme, und dazu die anzahl wie oft er sich doppelt mit einer ID befasst hat...

Hoffe das geht iwi mit SQL...


----------



## Alex F. (17. Juni 2010)

Ja es gibt vermutlich einen Befehl. Aber da du uns ja das dbms nicht nennst ist es auch schwer dir zu helfen.

bei Microsoft könntest du mal nach rank over , dense rank  oder ähnlichem suchen bei anderen systemen gibt es auch andere lösungen


----------



## Prengepower (17. Juni 2010)

na ich arbeite mit oracle.. glaube version 10...

die abfragen mache ich bzw. brauche ich für Talend Open Studio


----------



## Prengepower (21. Juni 2010)

also wie gesagt ich arbeite mit oracle... könnte sonst aber auch mit MySQL arbeiten und da vorher die daten reinfeuern


----------



## Yaslaw (21. Juni 2010)

IN MySQL kannst du es mit eigenen Variablen lösen


```
SELECT
	id,
	erstes_datum,
	name,
	COUNT(*) AS anzahl
FROM
	(
		SELECT
			id,	
			datum,
			name,
			@datum := if(@letzteId = id AND @letzterName = name, @datum, datum) AS erstes_datum,
			@letzteId := id,
			@letzterName := name
			
		FROM
			(SELECT @letzteId:=0, @letzterName:='', @datum = '') AS vars,
			(SELECT * FROM test2 ORDER BY id, datum) AS daten1
	) AS daten2
GROUP BY
	id,
	erstes_datum,
	name;
```
Ergibt dann

```
id | erstes_datum | name | anzahl
1 | 1.1 | A | 2
1 | 2.1 | B | 1
2 | 1.1 | A | 1
3 | 2.1 | C | 1
4 | 2.1 | A | 1
4 | 2.1 | C | 1
4 | 4.1 | A | 1
5 | 5.1 | B | 2
6 | 2.1 | A | 1
6 | 3.1 | B | 1
6 | 3.1 | C | 1
7 | 5.1 | A | 1
```


----------



## Prengepower (21. Juni 2010)

Also das ist ja wirklich schon sehr schön.
Aber lässt sich das Statement noch so anpassen, dass nur die Namen angezeigt werden, die eine ID doppelt hatten?
Sozusagen das folgendes rauskommt:

Id | Name | Anzahl
1 | A | 2 (da direkt aufeinander folgende Dopplungen nicht berücksichtigt werden)
4 | A | 2


----------



## Yaslaw (21. Juni 2010)

Ja, hängt am Schluss noch die folgende Zeile dazu und lösch im ersten select das [erstes_datum]

```
HAVING anzahl > 1
```

Dass sieht dann so aus

```
SELECT
	id,
	name,
	COUNT(*) AS anzahl
FROM
	(
		SELECT
			id,	
			datum,
			name,
			@datum := if(@letzteId = id AND @letzterName = name, @datum, datum) AS erstes_datum,
			@letzteId := id,
			@letzterName := name
			
		FROM
			(SELECT @letzteId:=0, @letzterName:='', @datum = '') AS vars,
			(SELECT * FROM test2 ORDER BY id, datum) AS daten1
	) AS daten2
GROUP BY
	id,
	erstes_datum,
	name
HAVING anzahl > 1
```


----------



## Prengepower (21. Juni 2010)

okay cool aber da wird jetzt noch nicht herausgefilter, wenn 2 namen sich direkt hintereinander mit einer ID beschäftigen oder? das sollte ja sein.. es soll nur gezählt werden wenn zwischen 2 namen noch ein anderer ist 

aber shconmal danke


----------



## Yaslaw (21. Juni 2010)

Aso. Die Anzahl sollte also nicht auf die 'Unterdrückten' gezählt werden...

1) Unterdrücken von aufeinanderfolgenden Usern bei gleicher id
2) Anzahl der Kombinationen id & name ohne die unterdrückten Einträge

Das ergibt etwa sowas

```
-- Zählen der Kombination id, name
SELECT
	id, 
	name,
	count(*) AS anzahl
FROM
	(
		-- aufeinanderfolgende namen mit gleicher id und gleichem erstes_datum unterdrücken
		SELECT
			id,
			erstes_datum,
			name
		FROM
			(
				-- erstes_datum ermiteln
				SELECT
					id,	
					datum,
					name,
					@datum := if(@letzteId = id AND @letzterName = name, @datum, datum) AS erstes_datum,
					@letzteId := id,
					@letzterName := name
					
				FROM
					(SELECT @letzteId:=0, @letzterName:='', @datum = '') AS vars,
					(SELECT * FROM test2 ORDER BY id, datum) AS daten
			) AS daten
		GROUP BY
			id,
			erstes_datum,
			name
	) AS daten
GROUP BY
	id, 
	name
```


----------



## Prengepower (21. Juni 2010)

okay. ich werde das heute versuchen und dann mal rückmeldung geben


----------



## Prengepower (22. Juni 2010)

hat super geklappt danke


----------

