SQL Custom and Eval / Parse (and \!\!\!...)Hi!
I do a lot of queries that can't use the JMP query builder and have to be written in SQL Custom.
But as I also want to generalize my code I have to integrate a lot of eval / inserts and \!
Here is an example:
Code not yet generalized
New SQL Query(
Connection(
"ODBC:blabla"
),
QueryName( "v_test_run" ),
CustomSQL(
"SELECT \!"t1\!".lot_id
FROM \!"public\!".\!"v_test_run\!" \!"t1\!"
WHERE ( ( ( \!"t1\!".test_run_timestamp >= '2020-11-01 15:25:11' ) ) ) ;"
)
) << Modify;
Code Generalized to include a date:
gbStr = Eval Insert("
New SQL Query(
Connection(
\!"ODBC:blabla\!"
),
QueryName( \!"v_test_run\!" ),
CustomSQL(
\!"SELECT \!\!\!"t1\!\!\!".lot_id
FROM \!\!\!"public\!\!\!".\!\!\!"v_test_run\!\!\!" \!\!\!"t1\!\!\!"
WHERE ( ( ( \!\!\!"t1\!\!\!".test_run_timestamp >= '^date_deb^' ) ) ) ;\!"
)
) << Modify;
");
Eval( Parse( gbStr ) );Is there any other method that would save me from having to juggle with these \!\!\! symbols?
On complex scripts it's really difficult to handle and debug!
Thank you
Data AccessBetreff: SQL Custom und Eval / Parse (und \!\!\!...)Super, das ist wirklich sehr praktisch! Und da wir gerade die Datenbank erstellt haben und ich der Hauptakteur dieser Erstellung war, habe ich nur dafür gesorgt, dass kein Tabellenname oder Variablenname Klammern oder Leerzeichen enthält, sodass diese Verallgemeinerung vereinfacht werden sollte.
Betreff: SQL Custom und Eval / Parse (und \!\!\!...)Ich gehe gerne einen anderen Weg und vermeide unintuitive eval-Parse-Kombinationen, wo ich sie für andere Zwecke recht nützlich finde.
Oft habe ich komplexe Abfragen (eingebaut in einfaches SQL von anderen Tools wie SQL-Entwickler). Und ich muss einige Variablen ändern.
Das beigefügte Beispiel zeigt, wie es mit großen Klassendatentabellen funktioniert, es würde jedoch für alle ODBC-Verbindungen auf ähnliche Weise funktionieren.
Ich bereite einfach meine Verbindungszeichenfolge (hier nicht verwendet) und die SQL-Abfrage in einer Zeichenfolgenvariablen vor, die dem Objekt "Neue SQL-Abfrage" übergeben wird.
Ich verwende "assign" (anstelle von "="), weil es gut für große Abfragen und Code-Folding funktioniert.
Und ich bin flexibler, um auch offene Datenbankfunktionen zu verwenden oder das SQL auf andere Weise zu verarbeiten.
Normalerweise werden die doppelten Anführungszeichen in einem einfachen SQL nicht benötigt (und ich versuche es auch zu vermeiden), es sei denn, Sie haben Namen mit Leerzeichen usw. wie "Big Class".
Names Default To Here( 1 );
cdt = Open( "$Sample_Data\Big Class.jmp" );
age = "15";
// define custom SQL with placeholder
Assign( sql_str, "SELECT t1.name, t1.age, t1.sex, t1.height,
t1.weight
FROM \!"Big Class\!" t1
WHERE ( ( ( t1.age IN ( &age ) ) ) ) ;" );
// fill placeholder
Substitute Into( sql_str, "&age", "15" );
// execute query
dt_age = New SQL Query( Version( 130 ), Connection( "JMP" ), JMP Tables( cdt ), QueryName( "aged" || "_" || age ), CustomSQL( sql_str ) ) << Run;
Betreff: SQL Custom und Eval / Parse (und \!\!\!...)Ich stimme zu, dass diese Syntax nur offensichtlich ist, wenn Sie sie verstehen, und selbst dann ist sie verwirrend.Kasse diesen Wunschlisteneintrag eine Eval Expr First()-Funktion einzuführen, wäre das vielleicht intuitiver?
Betreff: SQL Custom und Eval / Parse (und \!\!\!...)Ich würde die Trennzeichen \[ und ]\ verwenden, um doppelte Anführungszeichen in die Zeichenfolge aufzunehmen.
date_deb = "to_date('01-Mar-2019', 'dd-mon-yyyy')";
gbStr = Eval Insert("\[
New SQL Query(
Connection(
"ODBC:blabla"
),
QueryName( "v_test_run" ),
CustomSQL(
"SELECT "t1".lot_id
FROM "public"."v_test_run" "t1"
WHERE ( ( ( "t1".test_run_timestamp >= ^date_deb^ ) ) ) ;"
)
) << Modify;
]\");
write(gbstr);
Eval( Parse( gbStr ) );
Ausgang:
New SQL Query(
Connection(
"ODBC:blabla"
),
QueryName( "v_test_run" ),
CustomSQL(
"SELECT "t1".lot_id
FROM "public"."v_test_run" "t1"
WHERE ( ( ( "t1".test_run_timestamp >= to_date('01-Mar-2019', 'dd-mon-yyyy') ) ) ) ;"
)
) << Modify;Betreff: SQL Custom und Eval / Parse (und \!\!\!...)Vielen Dank! Ich hatte diesen Artikel gelesen und versucht, aber ich habe immer noch Schwierigkeiten, dieses eval zu meistern (eval expr (expr))
Betreff: SQL Custom und Eval / Parse (und \!\!\!...)Es gibt einige Optionen, die in beschrieben sind Dieser Artikel , empfehle ich, mit Eval( Eval Expr()) zu beginnen und dann jedes Stück, das Sie ersetzen müssen, mit Expr() zu umschließen und \[ ... ]\ zu verwenden, um die Anzahl der maskierten Zeichen zu reduzieren.Es könnte etwa so aussehen:
Eval( Eval Expr(
New SQL Query(
Connection(
"ODBC:blabla"
),
QueryName( "v_test_run" ),
CustomSQL(
Expr( "\[SELECT "t1".lot_id
FROM "public"."v_test_run" "t1"
WHERE ( ( ( "t1".test_run_timestamp >= ']\" || date_deb || "' ) ) ) ;")
)
) << Modify
) );
Betreff: SQL Custom und Eval / Parse (und \!\!\!...)@pmroz Ich habe etwas Ähnliches wie oben versucht. Nach der Ausführung von benutzerdefiniertem SQL wird am Ende des Protokolls das Ergebnis 1 zurückgegeben. Können Sie bitte das Ergebnis 1 näher erläutern? Ist es der Rückgabecode Eval( Parse( gbStr ) ), den Sie in Ihrem Skript erwähnt haben?

Betreff: SQL Custom und Eval / Parse (und \!\!\!...)Leider verwende ich den Query Builder nicht. Ich würde vermuten, dass der Rückgabewert 1 wahr ist und Erfolg anzeigt. Aber das könnte eine wilde Vermutung sein.:)
Betreff: SQL Custom und Eval / Parse (und \!\!\!...)@pmroz, danke für Ihre Antwort. Können Sie mir bei der Überprüfung des folgenden Skripts helfen?
SQL-Abfragen benötigen normalerweise einige Minuten, um auf die Datenbank zuzugreifen. Das Löschen von Zeilen (wenn :rank >1) wird manchmal nicht ausgeführt, kann aber manuell durchgeführt werden. Ich habe keine Ahnung … bin mir nicht sicher, ob mein Skript ein Problem hat?
date_deb = "to_date('01-Mar-2019', 'dd-mon-yyyy')";
gbStr = Eval Insert("\[
dt1 = New SQL Query(
Connection(
"ODBC:blabla"
),
QueryName( "v_test_run" ),
CustomSQL(
"SELECT "t1".lot_id
FROM "public"."v_test_run" "t1"
WHERE ( ( ( "t1".test_run_timestamp >= ^date_deb^ ) ) ) ;"
)
) << Run foreground;
]\");
write(gbstr);
Eval( Parse( gbStr ) );
dt1 << New Column( "Rank", Numeric, "Continuous", Format( "Best", 12 ) );
dt1:Rank << set Formula( Col Rank( :DATE* -1, :ID ) );
dt1 << Row Selection(select where(:Rank > 1 ));
dt1 << delete rows;
Betreff: SQL Custom und Eval / Parse (und \!\!\!...)Ich denke, die Auswertung der Formeln dauert einige Zeit.
Ein „wait(0)“ würde JMP zum Beenden zwingen, bis die Zeilenauswahl abgeschlossen ist (siehe Skript) und die Löschung erfolgen kann.
Ich würde Ihnen wirklich empfehlen, den Zeichenfolgenteil so klein wie möglich zu halten, da dieser immer fehleranfällig und schwer zu lesen ist.
Darüber hinaus besteht die großartige Möglichkeit, mithilfe von JMP-Tabellen diese Art von Problemen herauszufinden und Skripte für die Community zu schreiben, die jeder sofort ausführen kann.
Edited: replaced "\C:\Program Files\JMP\JMPPRO\18\Samples\Data" by "$SAMPLE_DATA"
Names Default To Here( 1 );
// date_deb = "to_date('01-Mar-2019', 'dd-mon-yyyy')";
date_str = "2008-06-19";
/*
gbStr = Eval Insert("\[
dt1 = New SQL Query(
Connection(
"ODBC:blabla"
),
QueryName( "v_test_run" ),
CustomSQL(
"SELECT "t1".lot_id
FROM "public"."v_test_run" "t1"
WHERE ( ( ( "t1".test_run_timestamp >= ^date_deb^ ) ) ) ;"
)
) << Run foreground;
]\");
*/
dt1_sql = Eval Insert(
"\[SELECT t1.Date, t1.State, t1."Flu Cases", t1.Region,
t1."Population (July 2009)"
FROM "Seasonal Flu" t1
WHERE ( ( ( t1.Date >= JMPDATE('^date_str^') ) ) ) ;]\"
);
dt1 = New SQL Query(
Version( 130 ),
Connection( "JMP" ),
JMP Tables( ["Seasonal Flu" => "$SAMPLE_DATA\Seasonal Flu.jmp"] ),
QueryName( "SQLQuery1" ),
CustomSQL( dt1_sql )
) << run;
// Write( gbstr );
// Eval( Parse( gbStr ) );
dt1 << New Column( "Rank", Numeric, "Continuous", Format( "Best", 12 ) );
dt1:Rank << set Formula( Col Rank( :DATE * -1, /* :ID */ :State) );
wait(0);
dt1 << Row Selection( select where( :Rank > 1 ) );
dt1 << delete rows;
Betreff: SQL Custom und Eval / Parse (und \!\!\!...)@Georg, danke für den Vorschlag. Es ist wirklich eine gute und clevere Idee , den String-Teil so klein wie möglich zu halten. Ich habe es probiert und das Löschen schlägt mit wait(0) trotzdem fehl. Aber mit wait(1) funktioniert es. Wenn ich jedoch auf größere Daten aus dem SQL-Rechenzentrum zugreife (wahrscheinlich dauert es ein paar Minuten, um die Daten vom Server abzurufen), funktioniert es bis wait(5). Ich schätze, dass die Berechnung von col rank() normalerweise etwas Zeit braucht. Größere Daten bedeuten mehr Zeit für die Berechnung. Wenn die Zeilenauswahl ausgeführt wird, bevor die Berechnung des Col Ranks abgeschlossen ist, schlägt das Löschen fehl. Gibt es eine Möglichkeit festzustellen, ob die Berechnung abgeschlossen ist? Wenn ja, kann ich die IF-Funktion verwenden, um den nächsten Schritt auszuführen.
Betreff: SQL Custom und Eval / Parse (und \!\!\!...)@ReliabilityWolf, im Allgemeinen würde ich versuchen, die Filterung in der Datenbank durchzuführen, es hängt also von der SQL-Sprache ab, die Sie verwenden (Sie können in SQL auch Rangfolge mit Unterauswahl verwenden). Und Sie gewinnen viel Zeit für unnötigen Verkehr.
Außerdem würde ich die Verwendung einer Formel hierfür vermeiden. Wenn Sie eindeutige Werte für die ID haben möchten, können Sie in SQL sortieren und doppelte Zeilen auswählen und löschen, siehe unten. Die Datenbank erledigt diese Aufgaben normalerweise viel schneller als Ihr Client.
Bezüglich Formeln hilft bei Bedarf vielleicht die Tabellenmeldung "Formeln ausführen" bzw. "Formeln erneut ausführen". Oder du kannst Formeln löschen, bzw. die Ergebnisse direkt in die Spalte schreiben...
Names Default To Here( 1 );
date_str = "2008-06-19";
dt1_sql = Eval Insert(
"\[SELECT t1.Date, t1.State, t1."Flu Cases", t1.Region,
t1."Population (July 2009)"
FROM "Seasonal Flu" t1
WHERE ( ( ( t1.Date >= JMPDATE('^date_str^') ) ) )
order by
t1.State, t1.date desc;]\"
);
dt1 = New SQL Query(
Version( 130 ),
Connection( "JMP" ),
JMP Tables( ["Seasonal Flu" => "$SAMPLE_DATA\Seasonal Flu.jmp"] ),
QueryName( "SQLQuery1" ),
CustomSQL( dt1_sql )
) << run;
dt1 << Select Duplicate Rows( Match( :State ) ) << delete rows();
Betreff: SQL Custom und Eval / Parse (und \!\!\!...)Ich schätze Ihre neue Richtung hinsichtlich der Filterung in der Datenbank sehr. Lassen Sie mich einen Blick darauf werfen. Nochmals vielen Dank.