繁体   English   中英

从数据库中的所有表汇总字段

[英]Summing a field from all tables in a database

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

id site votes_up votes_down

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

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

如何在PHP中做到这一点?

提前致谢,

约翰

您可以执行以下操作(警告: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

但是,正如Dav所问,您的数据是否必须像这样? 有很多更有效的方法来存储此类数据。

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

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上)。

基本思想是在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";
}

这是应该完成的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)

“我允许用户将表添加到数据库中。” -希望您所有的用户都是友好,可信赖和有能力的。 您是否担心人们会删除或截断表,创建不正确的新表而破坏您的代码或诸如此类的事情? 当用户可以直接登录数据库并更改架构时,您具有哪种安全性?

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

以防万一您想要找到其他人之后的样子,这里有一张表可以满足您的需求:

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')

我强烈建议您重新考虑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM