各位,
我经常需要来自不同来源的数据并将它们组合起来。 由于某些查询可能需要很多时间,我编写了一个脚本,在后台启动多个查询并在最后合并数据。 然而,要找到触发器、何时完成所有查询以及何时开始处理结果并不是那么容易。 在下面的脚本中,我测试了两种方法(通过“OnRunComplete”设置标志并测试结果表是否存在)。 它们相当有效,但我认为可能有更好的方法。
一个问题是,如果其中一个查询没有提供表,则循环将无限运行。 另一个问题是,脚本并不能真正控制查询是否仍然处于活动状态。
该脚本当前设置为调试模式,无需数据库连接即可测试此行为。
有什么改进的想法吗? 谢谢,BR
// Purpose:
// Start two database Queries (from different sources) in parallel and in background
// Wait for queries to finish
// and combine result
// JMP 15.0 Win10
//
// Details:
// After both queries are started in background
// a loop is started, that queries when both tables are existing
// In a previous version I worked with setting a flag ("OnRunComplete( B_QUERY_FINISHED = 1 )")
//
// Problem:
// A better solution would be to test, whether DB query is still running, but how?
// If the database query ends unexpectedly (by passing no table), the loop runs infinetely
Names Default To Here( 1 );
Clear Log();
// debug_mode: 0 - query from database / 1 - make table
// for database query the connectionstring must be correct
debug_mode = 1;
A_QUERY_FINISHED = 0;
B_QUERY_FINISHED = 0;
A_NAME = "A_Table";
B_NAME = "B_Table";
// new function to check whether background query is finished (= table does exists)
table_exists = Function( {table_name},
Names Default To Here( 1 );
table_lst = Get Data Table List();
table_name_lst = {};
For( i = 1, i <= N Items( table_lst ), i++,
Insert Into( table_name_lst, table_lst[i] << get name() )
);
Return( If( Contains( table_name_lst, table_name ) > 0, 1, 0 ) );
);
If( table_exists( A_NAME ) | table_exists( B_NAME ) ,
Throw( eval insert ("^A_NAME^ or ^B_NAME^ open! Please close " ))
);
// Define query
sql_str = "Select * from dual";
A_sql_str = sql_str;
B_sql_str = Substitute( sql_str, "A_scheme", "B_scheme" );
// Database query expression in backgroud
nsqlq_A_expr = Expr(
New SQL Query( Connection( "ODBC:DSN=XXX;DBQ=YYY;" ), QueryName( A_Name ), CustomSQL( A_sql_str ) ) <<
Run Background( OnRunComplete( A_QUERY_FINISHED = 1 ) )
);
nsqlq_B_expr = Expr(
New SQL Query( Connection( "ODBC:DSN=ZZZ;DBQ=AAA;" ), QueryName( B_Name ), CustomSQL( B_sql_str ) ) <<
Run Background( OnRunComplete( B_QUERY_FINISHED = 1 ) )
);
// Create table expression for Debugging
A_expr = Expr(
New Table( "A_Table", Add Rows( 1 ), Compress File When Saved( 1 ), New Column( "DUMMY", Character, "Nominal", Set Values( {"X"} ) ) )
);
B_expr = Expr(
New Table( "B_Table", Add Rows( 1 ), Compress File When Saved( 1 ), New Column( "DUMMY", Character, "Nominal", Set Values( {"X"} ) ) )
);
// start queries only in case of no debug_mode
If( debug_mode == 0,
Eval( nsqlq_A_expr );
Eval( nsqlq_B_expr );
);
start_time = Tick Seconds();
timestep = 1;
While( (table_exists( A_NAME ) & table_exists( B_NAME )) != 1,
Wait( timestep );
time_running = Round( Tick Seconds() - start_time, 0 );
Print( "waiting " || Char( time_running ) );
Show( table_exists( A_NAME ) );
Show( table_exists( B_NAME ) );
// For debugging only: create Table A after 5 seconds and Table B after 10 seconds
If( debug_mode == 1,
If( time_running > 5 & !table_exists( A_NAME ),
Eval( A_expr )
);
If( time_running > 10 & !table_exists( B_NAME ),
Eval( B_expr )
);
);
);
Wait( 1 );
Print( "Queries Finished" );
end_time = Tick Seconds();
Print( "Duration: " || Char( Round( end_time - start_time ) ) );
// concatenate
Try( Data Table( A_Name ) << Concatenate( Data Table( B_Name ), Append to first table ), Throw( Print( "Concatenate error" ) ) );
// Close( Data Table( B_Name ), nosave );
Data Table( A_Name )<< set name("Result Table");
Print( "Concatenating finished, script end " );我不相信我遇到过同样的问题,如果您仍然遇到问题,您可以发布带有错误的日志输出吗?或者如果您可以修复它,您可以让我知道如何更新示例脚本吗?
首选项中有一个 ODBC 设置导致了我类似的错误行为。 如果选中“如果可能,在后台运行查询”选项,则取消选中它并再次尝试您的脚本。 我认为这样做需要在速度和稳定性之间进行权衡,但如果您还没有尝试过,那么值得尝试。

谢谢@ih对于你的解决方案,它很好并且编程良好,所以我会尝试使用它。
在第一次测试中,我仍然看到一些计时问题(我想),因为参考(尚未)有效。
在语句“onRunComplete”中引入等待几秒钟然后可以工作,但不是解决方案。
我想这就是为什么我之前决定在引用可用表之前查询它。 我将进一步测试它。