cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
The Discovery Summit 2025 Call for Content is open! Submit an abstract today to present at our premier analytics conference.
See how to use JMP Live to centralize and share reports within groups. Webinar with Q&A April 4, 2pm ET.
Choose Language Hide Translation Bar
View Original Published Thread

创建 UI 以帮助构建 sql 查询

Tom_P
Level II

我希望创建一个 JMP UI,用户可以在其中选择要运行的程序,并将一些数据过滤器选项添加到 SQL 查询的末尾 [after where 语句] 或中间 [from 语句]。我的第一个问题是我认为我将用户输入/选择的数据错误地分配给了一个新变量(参见第 45 行 ---> DataParam_1)。然后我不确定如何分配过滤器选择语句(“AND ....”)并将其全部合并回一个更大的程序 SQL 语句。我试图获取所有用户输入的数据并将其传回一个名为 SUB_QUERY_1 的函数,在那里对其进行操作,最后将其传递给最终查询函数 SQL_Query_1 但这似乎不起作用。  

 

Clear Log();

SUB_QUERY_1 = Function( {Company_1, Company_2, Product_1, Product_2, Program_1, Program_2}, 
 //create query substatements for sql insertion after the main WHERE statement
 code_1 = If(
  (Company_1 != 0) & (Company_2 != 0), Eval Insert( "AND (COMPANY LIKE '%^Company_1^%' OR COMPANY LIKE '%^Company_2^%))" ),
  (Company_1 != 0), Eval Insert( "AND COMPANY LIKE '%^Company_1^%')" )
 );
  
 code_2 = If(
  (Product_1 != 0) & (Product_2 != 0), Eval Insert( "AND (PRODUCT LIKE '%^Product_1^%' OR PRODUCT LIKE '%^Product_2^%))" ),
  (Product_1 != 0), Eval Insert( "AND PRODUCT LIKE '%^Product_1^%')" )
 );

 Show( code_1, code_2 ); 
 //based on selected checkbox, run the query associated and insert code_1,code_2 at end of sql statement
 If(
  Program_1 != 0, SQL_Query_1( code_1, code_2 ),
  Program_2 != 0, SQL_Query_2( code_1, code_2 )
 );
);

//Final query to run based on altered info from user-interface & SUB_QUERY function
SQL_Query_1 = Function( {code_1, code_2},
 sql_statement_1 = Eval Insert( "Select *
    from TABLE.DATA
    WHERE SCANDATETIME > (SYSDATE - 30)" + code_1 + code_2 );
 Show( sql_statement_1 );
 Open Database( "DSN=xxx;UID=xxx;PWD=xxx;", sql_statement_1, "Table1" );
);

//SQL_Query_2 will be copy of SQL_Query_1 with different sql statement
//ignore that it is missing for the moment

//user-interface
ww = New Window( "Epi JMP Data Query",
 <

This post originally written in English (US) has been computer translated for you. When you reply, it will also be translated back to English (US).

2 ACCEPTED SOLUTIONS

Accepted Solutions
ErraticAttack
Level VI

回复:创建 UI 以帮助构建 sql 查询

@Tom_P ,我在这里创建了一个示例脚本,它使用显式范围控制来跟踪 UI 元素并提供更简洁的回调机制。这是一个示例脚本,需要一堆样板。如果您发现自己遵循这种方法并制作了许多交互式 UI 脚本,我建议创建一个库来自动执行样板代码(JSL 具有使用元编程在脚本运行前修改脚本的出色能力)。

 

下面的方法允许输入的持久化以及对回调的保护。

 

/* SQL Query */

self = New Namespace();
self:tool name = "SQL Setup";

Eval( Eval Expr(

self:initialize = Function( {},
 self = Namespace( Expr( self << Get Name ) );
 If( File Exists( "$TEMP/SQL_Setup.jsl" ),
  self:settings = Include( "$TEMP/SQL_Setup.jsl" );
 ,
  self:settings = [=>];
 );
 self:available companies = {"", "AAA", "BBB", "CCC"};
 self:available products = {"", "Prod1", "Prod2"};
 1
);

self:content = Function( {},
 V List Box(
  H List Box(
   Panel Box( "Select Program to Run:",
    V List Box(
     self:DataParam 1 = self:Check Box( {"Option_1"}, "dataparam 1", "single select(this, 1)" )
    ,
     self:DataParam 2 = self:Check Box( {"Option_2"}, "dataparam 2", "single select(this, 2)" )
    )
   )
  ,
   Panel Box( "Data Filter",
    Lineup Box( N Col( 3 ), Spacing( 3 ),
     V List Box( Align( "Right" ), Text Box( "Company:" ) )
    ,
     self:company 1 = self:Combo Box( self:available companies, "company 1" )
    ,
     self:company 2 = self:Combo Box( self:available companies, "company 2" )
    ,
     V List Box( Align( "Right" ), Text Box( "Customer:" ) )
    ,
     self:product 1 = self:Combo Box( self:available products, "product 1" )
    ,
     self:product 2 = self:Combo Box( self:available products, "product 2" )
    )
   )
  )
 ,
  H List Box(
   self:Button Box( "OK", "run sql" )
  ,
   Spacer Box( < (SYSDATE - 30)" + code_1 + code_2 );
 Show( sql_statement_1 );
 Open Database( "DSN=xxx;UID=xxx;PWD=xxx;", sql_statement_1, "Table1" );
);

) );

Eval( Eval Expr(

self:initialize();
New Window( self:tool name,
 <
pmroz
Super User

回复:创建 UI 以帮助构建 sql 查询

从 UI 的角度来看,这种方法要简单一些。函数很有用,但对于这个例子,我认为你不需要它们。这是对话框:

undefined

请注意,选择要运行的程序现在是一个单选框。因此,它不是为程序 1 选择选项和为程序 2 选择选项,而是服务于更单一的目的。

 

这是代码:

program_list = {"Option 1", "Option 2"};
company_list = {"AAA", "BBB", "CCC"};
product_list = {"Product 1", "Product 2"};

nw = new window("Option 1", << modal,
 panel box("Select Program to run:",
  program_rb = radio box(program_list),
 ),
 panel box("Select Company",
  hlistbox(
   comp_lb = list box(company_list),
   vlistbox(
    comp_right_bb = button box("", << set icon("Next"),
     << set function(
      function({this},
       comp_selected_lb << append(comp_lb << get selected);
      ),
     ),
    ),
    comp_left_bb  = button box("", << set icon("Prev"),
     << set function(
      function({this},
       comp_selected_lb << remove selected;
      ),
     ),
    ),
   ),
   comp_selected_lb = list box({}),
  ),
 ),
 panel box("Select Product",
  hlistbox(
   prod_lb = list box(product_list),
   vlistbox(
    prod_right_bb = button box("", << set icon("Next"),
     << set function(
      function({this},
       prod_selected_lb << append(prod_lb << get selected);
      ),
     ),
    ),
    prod_left_bb  = button box("", << set icon("Prev"),
     << set function(
      function({this},
       prod_selected_lb << remove selected;
      ),
     ),
    ),
   ),
   prod_selected_lb = list box({}),
  ),
 ),
 panel box("Actions",
  hlistbox(
   button box("OK", 
    continue_flag = 1;
    selected_company_list = comp_selected_lb << get items;
    selected_product_list = prod_selected_lb << get items;
   ),
   button box("Cancel", continue_flag = 0),
  ),
 ),
);

if (continue_flag,
// print(selected_company_list);
// print(selected_product_list);

 company_sql = "";
 for (i = 1, i <= nitems(selected_company_list), i++,
  one_company = selected_company_list[i];
  if (i == 1,
   company_sql = evalinsert(" AND (COMPANY LIKE '%^one_company^%'");
   ,
  // else
   company_sql = company_sql || evalinsert(" OR COMPANY LIKE '%^one_company^%'");
  );
 );
 company_sql = company_sql || ")";
// print(company_sql);

 product_sql = "";
 for (i = 1, i <= nitems(selected_product_list), i++,
  one_product = selected_product_list[i];
  if (i == 1,
   product_sql = evalinsert(" AND (PRODUCT LIKE '%^one_product^%'");
   ,
  // else
   product_sql = product_sql || evalinsert(" OR PRODUCT LIKE '%^one_product^%'");
  );
 );
 product_sql = product_sql || ")";
// print(product_sql);

 sql_statement = Eval Insert( 
"Select *
   from TABLE.DATA
  WHERE SCANDATETIME > (SYSDATE - 30)
    ^company_sql^
    ^product_sql");
 print( sql_statement );
// Open Database( "DSN=xxx;UID=xxx;PWD=xxx;", sql_statement_1, "Table1" );
);

7 REPLIES 7
ErraticAttack
Level VI

回复:创建 UI 以帮助构建 sql 查询

@Tom_P ,我在这里创建了一个示例脚本,它使用显式范围控制来跟踪 UI 元素并提供更简洁的回调机制。这是一个示例脚本,需要一堆样板。如果您发现自己遵循这种方法并制作了许多交互式 UI 脚本,我建议创建一个库来自动执行样板代码(JSL 具有使用元编程在脚本运行前修改脚本的出色能力)。

 

下面的方法允许输入的持久化以及对回调的保护。

 

/* SQL Query */

self = New Namespace();
self:tool name = "SQL Setup";

Eval( Eval Expr(

self:initialize = Function( {},
 self = Namespace( Expr( self << Get Name ) );
 If( File Exists( "$TEMP/SQL_Setup.jsl" ),
  self:settings = Include( "$TEMP/SQL_Setup.jsl" );
 ,
  self:settings = [=>];
 );
 self:available companies = {"", "AAA", "BBB", "CCC"};
 self:available products = {"", "Prod1", "Prod2"};
 1
);

self:content = Function( {},
 V List Box(
  H List Box(
   Panel Box( "Select Program to Run:",
    V List Box(
     self:DataParam 1 = self:Check Box( {"Option_1"}, "dataparam 1", "single select(this, 1)" )
    ,
     self:DataParam 2 = self:Check Box( {"Option_2"}, "dataparam 2", "single select(this, 2)" )
    )
   )
  ,
   Panel Box( "Data Filter",
    Lineup Box( N Col( 3 ), Spacing( 3 ),
     V List Box( Align( "Right" ), Text Box( "Company:" ) )
    ,
     self:company 1 = self:Combo Box( self:available companies, "company 1" )
    ,
     self:company 2 = self:Combo Box( self:available companies, "company 2" )
    ,
     V List Box( Align( "Right" ), Text Box( "Customer:" ) )
    ,
     self:product 1 = self:Combo Box( self:available products, "product 1" )
    ,
     self:product 2 = self:Combo Box( self:available products, "product 2" )
    )
   )
  )
 ,
  H List Box(
   self:Button Box( "OK", "run sql" )
  ,
   Spacer Box( < (SYSDATE - 30)" + code_1 + code_2 );
 Show( sql_statement_1 );
 Open Database( "DSN=xxx;UID=xxx;PWD=xxx;", sql_statement_1, "Table1" );
);

) );

Eval( Eval Expr(

self:initialize();
New Window( self:tool name,
 <

This post originally written in English (US) has been computer translated for you. When you reply, it will also be translated back to English (US).

Tom_P
Level II

回复:创建 UI 以帮助构建 sql 查询

感谢一百万个 ErraticAttach

 

当我替换回我的一些官方信息时,我收到一些错误消息:

 

点击运行并弹出 UI 后,嵌入式日志显示:

用户定义函数“按钮盒”与 JMP 函数“按钮盒”冲突。 使用范围引用(例如,Global:Button Box 或 Here:Button Box)调用您的用户定义函数。 脚本源中“按钮框”的其他用途将继续调用 JMP 函数。
用户定义函数“组合框”与 JMP 函数“组合框”冲突。 使用范围引用(例如,Global:Combo Box 或 Here:Combo Box)调用您的用户定义函数。 脚本源中“组合框”的其他用途将继续调用 JMP 函数。
用户定义函数“复选框”与 JMP 函数“复选框”冲突。 使用范围引用(例如,Global:Check Box 或 Here:Check Box)来调用用户定义的函数。 脚本源中“复选框”的其他用途将继续调用 JMP 函数。
“#38”

 

然后我选择程序 1 并点击确定,我看到:

第一个弹出窗口:[Microsoft][ODBC 驱动程序管理器] 无效的字符串或缓冲区长度

第二次弹出:查询失败的 SQL 语句的日志

 

日志内容如下:

code_1 = "AND COMPANY LIKE '%AAA%')";
code_2 = "AND PRODUCT LIKE '%Prod1%')";
sql_statement_1 = "";

无效的 SQL 语句:

{按钮( 1 )}

 

关于如何克服缺少 sql_statement 的任何想法?

This post originally written in English (US) has been computer translated for you. When you reply, it will also be translated back to English (US).

pmroz
Super User

回复:创建 UI 以帮助构建 sql 查询

从 UI 的角度来看,这种方法要简单一些。函数很有用,但对于这个例子,我认为你不需要它们。这是对话框:

undefined

请注意,选择要运行的程序现在是一个单选框。因此,它不是为程序 1 选择选项和为程序 2 选择选项,而是服务于更单一的目的。

 

这是代码:

program_list = {"Option 1", "Option 2"};
company_list = {"AAA", "BBB", "CCC"};
product_list = {"Product 1", "Product 2"};

nw = new window("Option 1", << modal,
 panel box("Select Program to run:",
  program_rb = radio box(program_list),
 ),
 panel box("Select Company",
  hlistbox(
   comp_lb = list box(company_list),
   vlistbox(
    comp_right_bb = button box("", << set icon("Next"),
     << set function(
      function({this},
       comp_selected_lb << append(comp_lb << get selected);
      ),
     ),
    ),
    comp_left_bb  = button box("", << set icon("Prev"),
     << set function(
      function({this},
       comp_selected_lb << remove selected;
      ),
     ),
    ),
   ),
   comp_selected_lb = list box({}),
  ),
 ),
 panel box("Select Product",
  hlistbox(
   prod_lb = list box(product_list),
   vlistbox(
    prod_right_bb = button box("", << set icon("Next"),
     << set function(
      function({this},
       prod_selected_lb << append(prod_lb << get selected);
      ),
     ),
    ),
    prod_left_bb  = button box("", << set icon("Prev"),
     << set function(
      function({this},
       prod_selected_lb << remove selected;
      ),
     ),
    ),
   ),
   prod_selected_lb = list box({}),
  ),
 ),
 panel box("Actions",
  hlistbox(
   button box("OK", 
    continue_flag = 1;
    selected_company_list = comp_selected_lb << get items;
    selected_product_list = prod_selected_lb << get items;
   ),
   button box("Cancel", continue_flag = 0),
  ),
 ),
);

if (continue_flag,
// print(selected_company_list);
// print(selected_product_list);

 company_sql = "";
 for (i = 1, i <= nitems(selected_company_list), i++,
  one_company = selected_company_list[i];
  if (i == 1,
   company_sql = evalinsert(" AND (COMPANY LIKE '%^one_company^%'");
   ,
  // else
   company_sql = company_sql || evalinsert(" OR COMPANY LIKE '%^one_company^%'");
  );
 );
 company_sql = company_sql || ")";
// print(company_sql);

 product_sql = "";
 for (i = 1, i <= nitems(selected_product_list), i++,
  one_product = selected_product_list[i];
  if (i == 1,
   product_sql = evalinsert(" AND (PRODUCT LIKE '%^one_product^%'");
   ,
  // else
   product_sql = product_sql || evalinsert(" OR PRODUCT LIKE '%^one_product^%'");
  );
 );
 product_sql = product_sql || ")";
// print(product_sql);

 sql_statement = Eval Insert( 
"Select *
   from TABLE.DATA
  WHERE SCANDATETIME > (SYSDATE - 30)
    ^company_sql^
    ^product_sql");
 print( sql_statement );
// Open Database( "DSN=xxx;UID=xxx;PWD=xxx;", sql_statement_1, "Table1" );
);

This post originally written in English (US) has been computer translated for you. When you reply, it will also be translated back to English (US).

Tom_P
Level II

回复:创建 UI 以帮助构建 sql 查询

@pmroz

我非常感谢您的帮助,也非常喜欢您的想法

 

当我按原样运行脚本时,嵌入式日志不会选择我的选择,而是显示空虚,即使我做出了选择

 

"Select *
   from TABLE.DATA
  WHERE SCANDATETIME > (SYSDATE - 30)
    )
    )"

如何补救?

This post originally written in English (US) has been computer translated for you. When you reply, it will also be translated back to English (US).

Tom_P
Level II

回复:创建 UI 以帮助构建 sql 查询

@pmroz

我很抱歉

这非常有效,我点击了选择但没有将它们移动到正确的部分以“选择”它们的值。

对不起,混合信息。

 

另一个很好的解决方案!

This post originally written in English (US) has been computer translated for you. When you reply, it will also be translated back to English (US).

ErraticAttack
Level VI

回复:创建 UI 以帮助构建 sql 查询

我正在使用您定义的函数。看起来您需要通过将第 195 行替换为将字符串连接在一起WHERE SCANDATETIME > (SYSDATE - 30) " || code_1 || " " || code_2 );

 

弹出窗口的发生是因为数据库具有虚假值。

 

关于重新定义内置函数的日志发生是因为函数名称反映了内置函数。如果您不想要日志消息,可以更改函数名称。

This post originally written in English (US) has been computer translated for you. When you reply, it will also be translated back to English (US).

Tom_P
Level II

回复:创建 UI 以帮助构建 sql 查询

是的,它现在可以正常运行

 

WHERE SCANDATETIME > (SYSDATE - 365)" || "^code_1^" || "^code_2^"

This post originally written in English (US) has been computer translated for you. When you reply, it will also be translated back to English (US).