Hilfe!
Hallo zusammen,
ich würde gerne folgendes Problem lösen. Hat jemand einen Vorschlag?
Es sollen folgende Tabellen angelegt werden.
1) Tabelle "Daten" hat folgende Felder:
sample name, marker, size1, size2
Zu jedem "sample name" gibt es mehrere Einträge im Feld marker, size1 und size1, wobei für jedes sample sich die gleichen "marker" wiederholen, z.b. für die samples A, B, C
sample name marker size_R1 size_R2
A X 1 7
A Y 2 8
A Z 3 9
B X 4 10
B Y 5 11
B Z 6 12
C X 13 16
C Y 14 17
C Z 15 18
Für jeden "marker" sollen jetzt entsprechende Tabellen in der Datenbank angelegt werden.
2) Tabelle "Marker X" mit folgenden Feldern:
sample name, size_R1, size_R2, size_P1, size_P2, size_P1/P2
Die Felder size_P1 und size_P2 sind f(x)-Berechnungsfelder aus size_R1 und size_R2 entsprechend. Das Feld size_P1/P2 ist ein f(x)-Berechnungsfeld aus size_P1 und size_P2. Gemäß der obigen Datentabelle, z.b.
sample name size_R1 size_R2 size_P1 size_P2 size_P1/P2
A 1 7
B 4 10
C 13 16
3) Tabelle "Marker Y" mit folgenden Feldern:
(analog wie bei Tabelle "Marker X")
sample name size_R1 size_R2 size_P1 size_P2 size_P1/P2
A 2 8
B 5 11
C 14 17
4) Tabelle "Marker Z" mit folgenden Feldern:
(analog wie bei Tabelle "Marker X")
sample name size_R1 size_R2 size_P1 size_P2 size_P1/P2
A 3 9
B 6 12
C 15 18
Die Tabellen für die einzelnen Tabellen "MarkerX, Y, Z" ziehen die Daten aus der Tabelle "Daten".
5) Tabelle "Sample"
In der Tabelle "Sample" sollen nun die Daten aus den "Marker"-Tabellen teilweise wieder zusammengeführt werden. Die Tabelle enthält folgende Felder:
sample name marker size_P1 size_P2 size_P1/P2
Vielen Dank,
Bertram
30 Antworten
-
Hallo Bertram, auch hier gehe ich wieder davon aus, dass alle Marker desselben Typs in einem Rutsch in die entsprechende Tabelle geschrieben werden sollen. Für Marker "X" könnte das Skript bspw. so aussehen:
for i in select Daten where marker = "X" do
let newM := (create Marker_X);
newM.(sample_name := i.sample_name);
newM.(size_R1 := i.size_R1);
newM.(size_R2 := i.size_R2)
end
Das müsste man aber für jeden Marker machen, in vorliegendem Beispiel also auch noch mal für die Marker "Y" und "Z", wobei die ersten beiden Zeilen jeweils angepasst werden müssten. Voraussetzung wäre weiterhin, dass die Markertabellen, hier 'Marker_X* auch bereits mit den entsprechender Feldern existieren. Denn mit Ninox kann man per Skript weder Tabellen erstellen noch dynamisch adressieren.
Die Übertragung in 'Sample' könnte man theoretisch in das obige Skript integrieren. Problem: Die Berechnungsfelder der eben neu erzeugten Datensätze sind zu diesem Zeitpunkt noch nicht initialisiert, würden also nur den Wert 0 zurückgeben.
Wenn die Formeln zur Berechnung von 'size_P1' und 'size_P2' nicht zu komplex sind, dann könnte man sie direkt in das Skript übernehmen statt nur auf die vorhandenen Berechnungsfelder der Marker-Tabellen zuzugreifen. Angenommen, die R-Werte würden jeweils mit 2 multipliziert und 'size_P1/P2' wäre die Summe von P1 und P2, dann könnte der erweiterte Code so aussehen:
for i in select Daten where marker = "X" do
let newM := (create Marker_X);
newM.(sample_name := i.sample_name);
newM.(size_R1 := i.size_R1);
newM.(size_R2 := i.size_R2)
let newS := (create Sample);
newS.(sample_name := newX.sample_name);
newS.(marker := tx.marker);
newS.(size_P1 := i.size_R1 * 2);
newS.(size_P2 := i.size_R2 * 2);
newS.('size_P1/P2' := newS.size_P1 + newS.size_P2)
end
Wobei alle size-Felder in der Tabelle 'Sample' Zahlenfelder sein müssten.
-
Ups, da waren zwei Tippfehler drin:
for i in select Daten where marker = "X" do
let newM := (create Marker_X);
newM.(sample_name := i.sample_name);
newM.(size_R1 := i.size_R1);
newM.(size_R2 := i.size_R2)
let newS := (create Sample);
newS.(sample_name := i.sample_name);
newS.(marker := i..marker);
newS.(size_P1 := i.size_R1 * 2);
newS.(size_P2 := i.size_R2 * 2);
newS.('size_P1/P2' := newS.size_P1 + newS.size_P2)
end
-
Hallo Der Copytexter,
vielen Dank für die Skripte. Wo müssen denn die Marker-Tabellen-Skripte platziert werden? Daten-Tabelle oder Marker-Tabellen? Und wo müssen sie platziert werden? Linke Spalte (nach Öffnen von "Felder bearbeiten") bei "Bei neuem Datensatz folgendes Skript ausführen" oder "Nach Änderungen folgendes Skript durchführen"?
Vielen Dank, Bertram
-
Da alle betreffenden Tabellen direkt per "select" bzw. "create" angesprochen werden, können die Skripte an beliebiger Stelle über eine Schaltfläche oder im Administratormodus über die Console ausgeführt werden. Wie gesagt: Der Code ist nicht an einen bestimmten Datensatz geknüpft, sondern führt die Operation einmalig für alle in der Tabelle 'Daten' vorhandenen Datensätze aus, die dem in der ersten Zeile angegebenen Marker entsprechen ("X").
Soll der Vorgang statt dessen jeweils manuell für einen bestimmten Datensatz angestoßen werden, dann müsste der Code anders aussehen. Der genaue Ablauf geht aus der Beschreibung aber nicht hervor, weshalb ich mich an der Aufgabenbeschreibung orientiert habe, die nach mejner Lesart lautet: Ich habe eine Tabelle 'Daten' und möchte deren (vorhandene) Datensätze auf verschiedene Tabellen verteilen.
-
Hallo Copytexter,
ok, ich habe jetzt das erste Skript als Button in der Tabelle "Marker X" eingerichtet. Wenn ich jetzt in das Feld "Marker" in dieser Tabelle den entsprechenden Namen des Markers eingebe (also X) und Button klicke, öffnet es die Tabelle "Daten" an der ersten Position wo der Name des Markers (X) gelistet ist? Es werden aber nicht alle Enträge der Tabelle "Daten" in denen der Marker X mit seinen Size_R1 und Size_R2 vorkommt in die Tabelle "Marker X" übertragen?
Gruß, Bertram
-
Hallo Betram, öffnet die Tabelle 'Daten'? Hm ... Ich habe die Versuchsanordnung mal nachgestellt und die Datenbank auf einen Server gelegt (einfach herunterladen und als "Archiv importieren"):
https://www.dropbox.com/s/tvb7lsl5iynckxi/Daten_Bertram.ninox?dl=0
-
Hallo Copytexter,
vielen Dank. Das funktioniert. Jetzt muss ich schauen, wo bei mir der Fehler liegt.
Gruß, Bertram
-
Hallo Copytexter,
die Skripte funktionieren inzwischen. Jetzt hänge ich aber an einer Sache fest:
Das Funktionsfeld (fx) size_P1/P2 enthält eine etwas kompliziertere Berechnung, so dass ich die Berechnung in den Marker-Tabellen ablaufen lassen und danach nur die Ergebnisse dieses Feldes als Wert in die Tabelle-sample übertragen möchte. Wenn ich newS.(size_P1/P2 := i.size_P1/P2) ins Skript schreibe, erhalte ich die Fehlermeldung: Die Tabellenspalte ist kein einfaches Datenfeld. Das ist korrekt, da es ja ein fx-Feld ist. Gibt es dafür eine Lösung? Läßt sich z.B. nur der Wert des fx-Feldes size_P1/P2 in ein einfaches Datenfeld umwandeln? Das Ergebnis des Feldes size_P1/P2 enthält Werte in der Form z.b. 234/456. Die Funktion, die in diesem Feld als Skript hinterlegt ist, lautet:
if 'size_P1' > 'size_P2' then number('size_P2') + "/" + number('size_P1')
else
number('size_P1') + "/" + number('size_P2')
end
Vielen Dank,
Bertram
-
Hallo Bertram, bisher war ich davon ausgegangen, dass alle "size"-Felder numerische Werte beinhalten. Das beispielhafte "234/456" wäre allerdings ein String (Text, Zeichenkette), deshalb müsste 'size_P1/P2' in der Tabelle 'Sample' ein Textfeld sein, um den entsprechenden Wert aus den Marker-Tabellen übernehmen zu können. Die betreffende Zeile würde dann lauten:
newS.('size_P1/P2' := i.'size_P1/P2')
Man könnte auch ganz anders herangehen und die Berechnungen gesondert durchführen, die Ergebnisse in Variablen speichern und diese dann den Feldern zuordnen:
for i in select Daten where marker = "X" do
let myR1 := i.size_R1;
let myR2 := i.size_R2;
let myP1 := myR1 * 2;
let myP2 := myR2 * 2;
let myP1P2 := "";
myP1P2 := if myP1 > myP2 then
text(myP2) + "/" + text(myP1)
else
text(myP1) + "/" + text(myP2)
end;
let newM := (create Marker_X);
newM.(sample_name := i.sample_name);
newM.(size_R1 := myR1);
newM.(size_R2 := myR2);
let newS := (create Sample);
newS.(sample_name := i.sample_name);
newS.(marker := i.marker);
newS.(size_P1 := myP1);
newS.(size_P2 := myP2);
newS.('size_P1/P2' := myP1P2)
end
Man könnte auf diese Weise auch in den Marker-Tabellen ganz auf Berechnungsfelder verzichten und die Ergebnisse in Datenfelder schreiben. Ich weiß aber nicht, ob das gewünscht ist.
-
Nanu, wo kommt denn dieses Translate-Zeugs her? Von mir ist das nicht.
-
Aaah, endlich Klingonisch.
Vielleicht ein neues Ninox Feature. ;-) -
Was auch immer es ist: Ich will das nicht!
-
Hallo Axel.
Das scheint von deinem Computer auszugehen. Bei mir wird nichts angehängt. -
So, habe Google aktualisiert. Mal sehen ...
-
Alle Erweiterungen deaktiviert ...
-
Aah! Eine davon war offenbar der Übeltäter!
-
Hallo Der Copytexter,
die Skripte funktionieren sehr gut und liefern jetzt schon nahezu alles was ich mir vorgestellt hatte. Nun hätte ich eine weitere Frage. Mit dem Button lassen sich bisher aus der Tabelle "Daten" die Inhalte in Tabelle "Marker" und "Sample" importieren. Die Inhalte bleiben momentan aber in Tabelle "Daten" und "Marker" stehen. Wenn ich nun neue csv-Daten in Tabelle "Daten" importiere und über den Button nach "Marker" und "Sample" überführe, werden natürlich alle "alten" Daten auch wieder importiert und liegen entsprechend nach und nach mehrfach vor. Wie lassen sich die bisherigen Skripte ergänzen, so dass nach dem einmaligen Transfer der Daten aus Tabelle "Daten" die Inhalte in dieser Tabelle und der Tabelle "Marker" gelöscht werden und nur in Tabelle "Sample" erhalten bleiben?
Vielen, Bertram
-
...Nachtrag: Durch Einfügen von newM.(delete this) werden die Inhalte aus Tabelle "Marker" gelöscht. Aber wie/wo mache ich das für die Inhalte in der Tabelle "Daten"?
for i in select Daten where marker = "X" do
let newM := (create Marker_X);
newM.(sample_name := i.sample_name);
newM.(size_R1 := i.size_R1);
newM.(size_R2 := i.size_R2);
newM.(delete this);
let newS := (create Sample);
newS.(sample_name := i.sample_name);
newS.(marker := i.marker);
newS.(size_P1 := i.size_R1 * 2);
newS.(size_P2 := i.size_R2 * 2);
newS.('size_P1/P2' := newS.size_P1 + newS.size_P2)
end; -
...Nachtrag: Oder gibt es im Skript die Möglichkeit, einen Befehl einzufügen, so dass immer nur die neu importierten Inhalte aus den Tabellen "Daten" und "Marker" nach "Sample" übertragen werden? Das wäre sogar die bessere Option, als die Daten zu löschen.
-
Hallo Bertram, 'Daten' ist also quasi eine Import-Tabelle, in welche regelmäßig Daten aus externen Quellen eingelesen werden? Die CSV-Dateien enthalten aber immer nur neue Daten, die noch nicht importiert wurden? Und die Daten der gleichnamigen Tabelle sollen nach Verarbeitung der Marker erhalten bleiben?
Dann wäre eine einfache Möglichkeit, in der Tabelle 'Daten' einen Merker zu setzen, ob der betreffende Datensatz schon verarbeitet wurde oder nicht. Also, ein Ja/Nein-Feld namens "Verarbeitet" oder so erstellen und den Standardwert auf "Nein" setzen.
Man müsste dann nur die select-Abfrage in der ersten Zeile ergänzen und in der letzten den Merker auf "Ja" setzen. Der Code dazwischen bliebe unverändert:
for i in select Daten where not Verarbeitet and marker = "X" do
let myR1 := i.size_R1;
let myR2 := i.size_R2;
let myP1 := myR1 * 2;
let myP2 := myR2 * 2;
let myP1P2 := "";
myP1P2 := if myP1 > myP2 then
text(myP2) + "/" + text(myP1)
else
text(myP1) + "/" + text(myP2)
end;
let newM := (create Marker_X);
newM.(sample_name := i.sample_name);
newM.(size_R1 := myR1);
newM.(size_R2 := myR2);
let newS := (create Sample);
newS.(sample_name := i.sample_name);
newS.(marker := i.marker);
newS.(size_P1 := myP1);
newS.(size_P2 := myP2);
newS.('size_P1/P2' := myP1P2);
i.(Verarbeitet := true)
end
Zur Sicherheit könnte man das Feld 'Verarbeit' verstecken und/oder mit "false" bei "Schreibbar wenn" vor manuellen Änderungen schützen. Nur so als Idee.
-
Noch eine grundsätzliche Anmerkung zum Datenmodell: Hat es eigentlich einen besonderen Grund, dass für jeden Marker eine Extra-Tabelle existiert? Da der Aufbau der Tabellen ja immer derselbe ist, könnte man ja auch alle Marker in einer Tabelle lassen und bei Bedarf nach dem Marker filtern bzw. gruppieren. Oder Ansichten für jeden Marker erstellen. So oder so: Man hätte nach wie vor Zugriff auf die Daten jedes einzelnen Markers und müsste nach dem Import nur noch die 'Sample'-Tabelle füllen.
-
Hallo Der Copytexter,
herzlichen Dank erstmal. Ich werde das Skript gleich ausprobieren. Der Grund warum zunächst alle Marker in Extra-Tabellen verteilt werden müssen ist, dass für die Felder "size_P1" und "size_P2" für jeden Marker andere Skripte hinterlegt sind. Es kann also z.b. Marker X nicht mit dem Skript für Marker Y berechnet.
Viele Grüße,
Bertram
-
Ah, okay, danke für die Erklärung. Wobei sich auch die verschiedenen Formeln je Marker mit Ninox umsetzen ließen. Aber das nur der Vollständigkeit halber. Wenn das mit den Extratabellen für dich so passt, dann kann man es natürlich auch so machen.
-
Hallo Der Copytexter,
ich hätte wieder eine Frage. Ich habe das Skript soweit angepasst, dass es jetzt gut funktioniert. Für den Marker X verwende ich folgendes Skript z.B.:
for i in select 'Daten' where not Verarbeitet and Marker = "X" do
let newM := (create Marker_X);
newM.('sample_name' := i.'sample_name');
newM.('size_R1' := i.'size_R1');
newM.('size_R2' := i.'size_R2');
newM.(Marker := i.Marker);
i.(Verarbeitet := true)
end;
for i in select Marker_X where not Verarbeitet do
let newS := (create Sample);
newS.('size_P1/P2' := i.'size_P1/P2');
newS.('sample_name':= i.'sample_name');
i.(Verarbeitet := true)
endDamit werden die Daten für den Marker X aus der Tabelle "Daten" korrekt in Tabelle "Marker" übertragen, die Werte für size_P1 und size_P2 sowie size_P1/P2 berechnet und anschließend in die Tabelle "Sample" übertragen. Und mit der "Verarbeitet"-Funktion kommt es auch nicht mehr zu einem doppelten Eintrag.
Folgende Ergänzung im Skript wäre jetzt noch wünschenswert: Im ersten Schritt wird in der Tabelle "Sample" der sample_name über dass Tastatur eingegeben und dananch wird der Button mit dem Skript betätigt. Durch das Skript sollte jetzt nur der Datensatz aus der Tabelle "Daten" bearbeitet werden, der den entsprechend gleichen sample_name der Tabelle "Sample" hat. Ich habe schon versucht im Skript in der ersten Zeile den Befehl: if sample_name := sample_name then einzufügen, aber da passiert nichts?!
Wie lässt sich das realisieren?
Vielen Dank, Bertram
-
Hallo Bertram, ich verstehe leider überhaupt nicht, was genau da jetzt passieren soll. Es gibt ein Skript, mit dem importierte Daten in die Tabellen 'Marker' und 'Sample' übertragen werden. Dazu werden alle noch nicht verarbeiteten Datensätze mit dem Marker "X" verarbeitet. Okay.
Jetzt soll in der Tabelle 'Sample' ein sample_name eingetippt werden? Und anhand dieser Eingabe soll WAS gemacht werden?
Content aside
- vor 3 JahrenZuletzt aktiv
- 30Antworten
- 1556Ansichten