cire48
Goto Top

SQL-Abfrage - Anzahl der Wechsel zählen

Hallo zusammen,

lässt sich folgendes mit einem SQL-Select umsetzen?
Gegeben sei eine Tabelle xyz mit der Spalte 1:

Spalte1 
a
b
b
c
b
b
b
b
d
b
b

Ich möchte die Anzahl der Wechsel wissen. Das gewünschte Ergebnis wäre 5:
a - > b
b -> c
c -> b
b -> d
d -> b

Lässt sich das mit einem SQL-Select lösen? Ein Group by funktioniert beispielweise nicht, das würde zum Ergebnis 4 führen:
a
b
c
d

Pseudocode:

if "nächster Wert" ungleich "aktueller Wert" then
1
else
0

Dankeschön.

Content-Key: 324452

Url: https://administrator.de/contentid/324452

Ausgedruckt am: 19.03.2024 um 02:03 Uhr

Mitglied: ukulele-7
ukulele-7 21.12.2016 um 16:10:41 Uhr
Goto Top
Ja wenn du eine Spalte für die Reihenfolge hast, idealerweise ein Integer der hoch zählt. Geht aber auch mit einem Zeitstempel oder etwas Anderes was man sinnvoll sortieren kann, dann wäre aber der SQL Server relevant.
Mitglied: SeaStorm
SeaStorm 21.12.2016 um 16:27:37 Uhr
Goto Top
prinzipiell würde sich sowas über FETCH & Cursor lösen lassen (https://msdn.microsoft.com/de-de/library/ms180152.aspx)

Aber was willst du denn am Ende damit erreichen? Klingt irgendwie für mich erst mal wenig Sinnvoll, als Aufgabe für einen SQL
Mitglied: Cire48
Cire48 21.12.2016 um 16:32:36 Uhr
Goto Top
MSSQL / Sql Server 9.0.4035

Ein Timestamp ist vorhanden.
Mitglied: Cire48
Cire48 21.12.2016 um 16:33:57 Uhr
Goto Top
Zudem habe ich auch einen Wert der hoch zählt. Eine "Entry No".
Mitglied: jan.xb
jan.xb 21.12.2016 um 16:55:53 Uhr
Goto Top
Wenn wir deine konkreten Daten und den Anwendungsfall kennen wuerden, gaebe es da bestimmt auch andere sinnvolle(-re) Loesungen..
Mitglied: ukulele-7
ukulele-7 21.12.2016 um 16:59:05 Uhr
Goto Top
Ist die Entry No. lückenlos? Dann ginge

SELECT	count(*) AS anzahl_wechsel
FROM	tabelle t1
INNER JOIN tabelle t2
ON		t1.entry_no = t2.entry_no + 1
WHERE	t1.spalte1 != t2.spalte1

Ist die Reihenfolge nicht lückenlos oder liegt ein Zeitstempel zugrunde würde ich mit ROW_NUMBER() arbeiten und darauf joinen. Das gibts allerdings bei MySQL nicht.

Von einem Cursor würde ich generell abraten, allein schon wegen der gruseligen Performance.
Mitglied: Cire48
Cire48 22.12.2016 um 07:46:29 Uhr
Goto Top
Leider ist die Entry No_ nicht lückenlos, sonst wäre dein Vorschlag perfekt.
Und row_number gibt es ja leider auch nicht.
Sonst noch jmd eine Idee?
Danke.
Mitglied: Cire48
Cire48 22.12.2016 um 07:49:16 Uhr
Goto Top
Ein Cursor ist mir in SQL prinzipiell bekannt, allerdings habe ich keinen Ansatz wie ich mein Problem damit lösen könnte.
Mitglied: SeaStorm
SeaStorm 22.12.2016 um 08:25:53 Uhr
Goto Top
naja im Grunde genau wie du es beschrieben hast.
du machst ne SP, mit der machst du einen Select auf die Daten die du haben willst und iterierst dann durch das Resultset durch


Zitat von @Cire48:

Pseudocode:

if "letzter Wert" ungleich "aktueller Wert" then
1
else


Es wäre noch immer interessant, was du damit erreichen willst, weil davon auch abhängen würde, was man in die SP schreibt
Mitglied: Cire48
Cire48 22.12.2016 um 08:26:23 Uhr
Goto Top
Konkreter Anwendungsfall siehe Anhang.

In der Spalte "Document No_" (Spalte 1 in meinem obigen Beispiel) sollen die Wechsel gezählt werden.
Der Wert "MU" ist immer gleich (entspricht "b" in meinem obigen Beispiel). Die anderen Werte sind verschieden.
upload
Mitglied: SeaStorm
SeaStorm 22.12.2016 um 08:43:02 Uhr
Goto Top
OK jetzt wissen wir leider nicht mehr als davor face-smile

Was ist der Sinn dahinter? Warum muss man wissen, wie oft da gewechselt wurde?

Verstehe mich nicht falsch, aber das sieht mir stark nach dem Typischen "Ich hatte eine Idee, wie ich was machen will, und sehe jetzt den Wald vor lauter Bäumen nicht mehr".

Vermutlich gibt es für das Problem eine Sinnvollere Lösung als das.
Nur als Info: Was du vorhast, bedeutet, das du bei jedem Aufruf der SP durch die komplette Tabelle(oder der Range davon) Zeilenweise durchratterst. Ich weiss nicht um was für Dimensionen es sich hier handelt, aber ganz prinzipiell ist das schrecklich unperformant und von der Vorgehensweise gruselig
Mitglied: SeaStorm
Lösung SeaStorm 22.12.2016 aktualisiert um 09:02:56 Uhr
Goto Top
Öhm ... und der Screenshot da sieht stark nach MSSQL aus ?! Zumindest nach dem SSMSS
Mitglied: Cire48
Cire48 22.12.2016 um 09:25:07 Uhr
Goto Top
Ja sorry, es ist MSSQL.
Mitglied: ukulele-7
Lösung ukulele-7 22.12.2016 um 11:51:34 Uhr
Goto Top
Na dann läßt sich das recht elegant lösen, hier mal ein Vorschlag
WITH t AS (
SELECT	ROW_NUMBER() OVER (PARTITION BY [Item No_] ORDER BY [Entry No_]) AS zeile,
		[Item No_],
		[Entry Type]
FROM	tabelle
	)
SELECT	t1.[Item No_],
		count(*) AS anzahl_wechsel 
FROM	t t1 
INNER JOIN t t2 
ON		t1.[Item No_] = t2.[Item No_]
AND		t1.zeile = t2.zeile + 1 
WHERE	t1.[Entry Type] != t2.[Entry Type]
GROUP BY t1.[Item No_]
Ich bin jetzt mal davon ausgegangen das die Wechsel von [Entry Type] gezählt werden sollen. [Entry No_] bestimmt die Reihenfolge, [Item No_] ist vermutlich dein Fremdschlüssel auf irgendwas, da macht eine Partitionierung eventuell Sinn.

Grundsätzlich gibt es mehrere Wege das zu lösen und anzupassen, mit MSSQL sollte sich das so am performantesten umsetzen lassen.
Mitglied: Biber
Lösung Biber 22.12.2016 um 14:20:17 Uhr
Goto Top
Moin ukulele-7,

wäre auch genau meine Strategie gewesen, wenn kein LEAD()/LAG() zur Verfügung steht.
Allerdings hätte ich nach der Beschreibung erwartet, dass die Wechsel von "Document_No_" Inhalt der Recherche sind und das Statement so geändert.

WITH t AS
(
  SELECT row_number() OVER (PARTITION BY [Item No_] ORDER BY [Entry No_]) AS zeile
         , [Item No_]
         , [Document_No_]
  FROM tabelle
)
SELECT t1.[Item No_]
       , count(*) AS anzahl_wechsel
FROM t t1
  INNER JOIN t t2
          ON t1.[Item No_] = t2.[Item No_]
         AND t1.zeile = t2.zeile + 1
WHERE t1.[Document_No_] != t2.[Document_No_]
GROUP BY t1.[Item No_];

Aber da der Beitrag inwischen als "Gelöst" markiert ist, hab ich mich wohl verlesen.

@Cire48
Dringendst zu empfehlen ist noch einer sinnvolle Einschränkung mit einer WHERE-Clause in einer neuen Zeile 07 - z.B. auf einen Zeitraum BETWEEN... oder bestimmte Item_No_.

Und eine andere Variante auch mit einer gewissen Aussagekraft wäre eine Erweiterung der CTE um ein Feld "Jahr_Monat" und eine Auswertung der Wechsel nicht über einzeln aufgeführte Item_No, sondern nach "Wechseln pro Jahr/Monat".

Grüße
Biber