对数据库中所有表的字段求和

时间:2009-08-05 23:24:15

标签: php mysql

我有一个名为“bookfeather”的MySQL数据库。它包含56个表。每个表都具有以下结构:

id site votes_up votes_down

“网站”的值是书名。 “votes_up”的值是一个整数。有时,“网站”的唯一值会出现在多个表格中。

对于整个数据库中的每个唯一值“site”,我想总结所有56个表中的“votes_up”。然后我想打印排名为“votes_up”的“网站”的前25个值。

我如何在PHP中执行此操作?

提前致谢,

约翰

5 个答案:

答案 0 :(得分:1)

你可以做这样的事情(警告:前面的SQL非常糟糕)

select site, sum(votes_up) votes_up
from (
    select site, votes_up from table_1
    UNION
    select site, votes_up from table_2
    UNION
    ...
    UNION
    select site, votes_up from table_56
) group by site order by sum(votes_up) desc limit 25

但是,正如戴维所问,你的数据是这样的吗?有更有效的方法来存储这种数据。

编辑:您刚刚在评论中提到过,您希望将来有超过56个表 - 在使用这种SQL之前,我会研究一下您可以使用UNION的表数的MySQL限制。

答案 1 :(得分:0)

可以使用如下语句生成Ian Clelland答案的UNION部分。表INFORMATION_SCHEMA.COLUMNS有一个TABLE_NAME列来获取所有表。

select * from information_schema.columns 
where table_schema not like 'informat%'
and column_name like 'VOTES_UP'

使用UNION ALL而不是UNION加入所有内部SELECT。 UNION正在进行隐式DISTINCT(在oracle上)。

答案 2 :(得分:0)

基本思想是在PHP中迭代所有表(使用SQL SHOW TABLES语句或类似语句),然后对每个表迭代行(SELECT site,votes_up FROM $table)。然后,对于每一行,针对您正在构建的阵列检查站点,将站点作为键并以值的形式投票。如果该站点已在阵列中,则适当增加其投票;否则,加上它。

模糊的类似PHP的伪代码:

// Build an empty array for use later
$votes_array = empty_array();

// Get all the tables and iterate over them
$tables = query("SHOW TABLES");
for($table in $tables) {
    $rows = query("SELECT site,votes_up FROM $table");

    // Iterate over the rows in each table
    for($row in $rows) {
          $site = $row['site'];
          $votes = $row['votes_up'];

         // If the site is already in the array, increment votes; otherwise, add it
         if(exists_in_array($site, $votes_array)) {
             $votes_array[$site] += $votes;
         } else {
             insert_into_array($site => $votes);
         }
    }
}

// Get the sites and votes as lists, and print out the top 25
$sorted_sites = array_keys($votes_array);
$sorted_votes = array_values($votes_array);
for($i = 0; $i < 25; $i++) {
    print "Site " . $sorted_sites[$i] . " has " . $sorted_votes[$i] . " votes";
}

答案 3 :(得分:0)

这是一个应该完成它的PHP代码片段。 我没有对它进行测试,因此可能会有一些拼写错误,确保您替换DB_NAME

$result = mysql_query("SHOW TABLES");
$tables = array();
while ($row = mysql_fetch_assoc($result)) {
    $tables[] = '`'.$row["Tables_in_DB_NAME"].'`';

}

$subQuery = "SELECT site, votes_up FROM ".implode(" UNION ALL SELECT site, votes_up FROM ",$tables);
// Create one query that gets the data you need
$sqlStr = "SELECT site, sum(votes_up) sumVotesUp
            FROM (
            ".$subQuery." ) subQuery
           GROUP BY site ORDER BY sum(votes_up) DESC LIMIT 25";
$result = mysql_query($sqlStr);
$arr = array(); 
while ($row = mysql_fetch_assoc($result)) { 
    $arr[] = $row["site"]." - ".$row["sumVotesUp"];
} 
print_r($arr)

答案 4 :(得分:0)

“我允许用户将表添加到数据库中。” - 我希望你的所有用户都是仁慈,值得信赖和有能力的。您是否担心人们丢弃或截断表,创建错误的新表来破坏您的代码或其他类似的东西?当用户可以直接登录到您的数据库并更改架构时,您有什么样的安全性?

这是关系数据库规范化的tutorial。也许它会有所帮助。

以防万一其他人想要找到这样的东西,这里有一张表可以做你想做的事情:

create database bookfeather;
create user bookfeather identified by 'bookfeather';
grant all on bookfeather.* to 'bookfeather'@'%';

use bookfeather;

create table if not exists book
(
    id int not null auto_increment,
    title varchar(255) not null default '',
    upvotes integer not null default 0,
    downvotes integer not null default 0,
    primary key(id),
    unique(title)
);

您可以使用UPDATE向上或向下投票:

update book set upvotes = upvotes + 1 where id = ?

添加新书就像添加另一行一样简单:

insert into book(title) values('grails in action')

我强烈要求你重新考虑。