将sprintf更改为简单的UNION

时间:2012-05-02 08:58:22

标签: php mysql

$STH_1 = $DBH_R->query("SELECT table_name                        
                         FROM information_schema.tables                        
                        WHERE table_name                        
                         LIKE 'v_c_ei\_9%'
                         ");
$stmts_1 = array();

while (($row_1 = $STH_1 -> fetch_assoc()) !== null){

$table_name = $row_1['table_name'];
$stmts_1[] = sprintf("SELECT *  
                        FROM $table_name
                       WHERE (ei_code = '1117') AND (DAY(date_time) != '00') 

                     "); 

} 

$stmt_1 = implode("\nUNION\n", $stmts_1);  
$stmt_1 .= "\nORDER BY date_time ASC";  

$STH_5_2 = $DBH_R->query($stmt_1);

while (($row_5_2 = $STH_5_2 -> fetch_assoc()) !== null){

好的,上面的脚本工作正常。但是,我想(必须)改变它的功能。我必须在UNION之前做选择(类似于ORDER BY ... LIMIT),但我知道 - 这不起作用。解决方案是将sprintif更改为UNION& UNION& UNION ......但问题是 - 我们不知道我们有多少桌子。

第一个查询中的表名称类似于

v_c_ei_9001
v_c_ei_9002
..........
v_c_ei_9030
..........
ect.

比q:当我们不知道我们有多少桌子时,如何将sprintif(也可能是阵列$ stmts_1)从abowe改为UNION? thnks

2 个答案:

答案 0 :(得分:0)

当您向ORDER BY的每个成分添加LIMITUNION条款时,如下所示:

while (($row_1 = $STH_1 -> fetch_assoc()) !== null){

$table_name = $row_1['table_name'];
$stmts_1[] = sprintf("SELECT *  
                      FROM $table_name
                      WHERE (ei_code = '1117') AND (DAY(date_time) != '00')
                      ORDER BY date_time DESC LIMIT 1 
                     "); 

} 

然后你执行以下操作:

$stmt_1 = implode("\nUNION\n", $stmts_1);  
$stmt_1 .= "\nORDER BY date_time ASC";                   // <---- remember this bit

$stmt_1中的结果字符串将如下所示:

SELECT *
FROM v_c_ei_9001
WHERE (ei_code = '1117') AND (DAY(date_time) != '00')
ORDER BY date_time DESC LIMIT 1
UNION
...
UNION
SELECT *
FROM v_c_ei_9030
WHERE (ei_code = '1117') AND (DAY(date_time) != '00')
ORDER BY date_time DESC LIMIT 1
ORDER BY date_time ASC                                 -- it's appearing down here!

如您所见,UNION的最终成分有两个 ORDER BY子句,这是语法错误。删除上面注释的remember this bit行,否则(如果需要重新排序统一查询),必须将UNION子查询设置为执行重新排序的外部查询:

$stmt_1 = "SELECT * FROM ("
$stmt_1 = implode("\nUNION\n", $stmts_1);  
$stmt_1 .= ") ORDER BY date_time ASC";

答案 1 :(得分:0)

正如我所见,展示自己的简单方法是写任何东西,而不是考虑问题的解决方案。这种情况类似于评估问题 - 如果问题的复杂性超出了观众的参与范围,那么评估它们的负面影响要比实际帮助问题的人更容易。不只是说话,而不是写任何东西。

对于所有可能遇到此类问题的人,我都会提供操作解决方案。

最简单的整体解决方案是指定执行主查询的表。 ORDER BY在主查询中获得的内容是在第一个查询上获得第一个辅助请求,通过预先排序执行主查询上的表。

通过这种方式,我们避免了主查询中的问题2x ORDER BY,因为ORDER BY子句被转移到第一个辅助请求。

$STH_1 = $DBH_R->query("SELECT c.table_name 
                          FROM v_c_country c 
                    INNER JOIN information_schema.tables i ON i.table_name = c.table_name 
                      ORDER BY c.country_name_pl ASC                                      ");

while (($row_1 = $STH_1 -> fetch_assoc()) != null){


$table_name = $row_1['table_name'];

$stmts_1[] = sprintf("SELECT *,'$table_name' AS table_name, time(date_time) AS time_dt, date(date_time) AS date_dt, MAX(date_time) AS MAXdate  
                        FROM $table_name
                       WHERE ei_code = '1117' AND (DAY(date_time) != '00') 
AND date_time = (SELECT MAX(date_time) FROM $table_name WHERE ei_code = '1117' AND index_released = '1')
                  "); 

}


$stmt_1 = implode("\nUNION\n", $stmts_1); 

$STH_5_2 = $DBH_R->query($stmt_1);

我经常在这里遇到问题的宽容态度,你知道如果有人提出等待我们的问题 - 寻找 - 请求帮助解决问题。我真的非常感谢所有伸出援助之手的人,并给出了非常有帮助的答案。这些人确实发生了。