2009-08-05 2 views
0

У меня есть база данных MySQL, называемая «bookfeather». Он содержит 56 таблиц. Каждый стол имеет следующую структуру:Суммирование поля из всех таблиц в базе данных

id site votes_up votes_down 

Значение для «сайта» - название книги. Значение для "votes_up" является целым числом. Иногда уникальное значение для «сайта» появляется в нескольких таблицах.

Для каждого уникального значения «сайт» во всей базе данных, я хотел бы суммировать «votes_up» из всех 56 таблиц. Затем я хотел бы напечатать первые 25 значений для «сайта», оцененных общим количеством голосов «голосов».

Как это сделать на PHP?

Спасибо заранее,

Джон

+6

Dare Я спрашиваю, почему у вас есть 56 таблиц с одинаковой структурой, а не одна таблица с 1 дополнительным полем, чтобы указать, в какой таблице будет запись * *? – Amber

+0

Я согласен с Дэвом, вам, вероятно, следует перепроектировать вашу базу данных. –

+0

Вот как я его настраивал. Я разрешаю пользователям добавлять таблицы в базу данных, поэтому я ожидаю, что число таблиц увеличится выше 56. – 2009-08-05 23:28:21

ответ

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) 

+0

Я попытался распечатать $ result в таблице, но у меня появилось сообщение об ошибке. Знаете ли вы, что код, который я должен использовать? Спасибо – 2009-08-06 00:30:31

+0

, вы должны запустить его, используя что-то вроде: $ arr = array(); while ($ row = mysql_fetch_assoc ($ result)) { $ arr [] = array ("site" => $ row ["site"], "sumVotesUp" => $ row ["sumVotesUp"]); } } print_r ($ arr); Для этого вам следует добавить псевдоним к сумме (votes_up) в запросе который входит в $ sqlStr. Я исправлю это в своем ответе. –

+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 

Но, как спросил Dav, делает ваши данные имеют быть таким? Существует гораздо более эффективный способ хранения таких данных.

Редактировать: Вы только что упоминали в комментарии, что вы ожидаете, что в будущем будет более 56 таблиц - я бы посмотрел на лимиты MySQL о том, сколько таблиц вы можете использовать UNION перед тем, как идти вперед с этим типом SQL.

+0

Я разрешаю пользователям добавлять таблицы в базу данных. Могу ли я сделать код, разрешающий объединениям до последней таблицы, независимо от того, сколько их в базе данных? – 2009-08-05 23:42:37

+0

Это не для объединения, но числа, вероятно, будут похожи ... «Максимальное количество таблиц, на которые можно ссылаться в одном соединении, равно 61. Это также относится к числу таблиц, на которые можно ссылаться в определении Это относится также к ЛЕВЫМ и ПРАВИЛЬНЫМ ВЗАИМОДЕЙСТВИЯМ ". Для MySQL 5.0 – Amber

+0

Другой источник говорит: «В инструкции SELECT имеется ограничение« 256 таблиц ». Вы можете использовать более 256 таблиц в запросе с операторами UNION, но такой запрос не может использоваться как представление или как подзапрос для инструкция SELECT.Если вы используете такой запрос напрямую, вы можете нажать ограничение пространства стека оптимизатора запросов примерно на 1300-1500 SELECT-s. » – Amber

0

Ответ UNI-части ответа Яна Клилланда может быть сгенерирован с использованием следующего утверждения. В таблице INFORMATION_SCHEMA.COLUMNS есть столбец TABLE_NAME для получения всех таблиц.

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

Соедините все внутренние SELECT с UNION ALL вместо UNION. UNION делает неявный DISTINCT (on oracle).

0

Основная идея - перебрать все ваши таблицы (с использованием оператора SQL SHOW TABLES или аналогичного) в PHP, затем для каждой таблицы выполнить итерацию по строкам(). Затем для каждой строки проверяйте сайт на массив, который вы строите на сайтах в качестве ключей, и голосуете как значения. Если сайт уже находится в массиве, соответствующим образом увеличивайте его голоса; в противном случае добавьте его.

Смутно 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"; 
}
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') 

Я настоятельно призываю вас пересмотреть.

Смежные вопросы