2012-01-03 4 views
1

В моей базе данных есть статьи новостей и сообщения в блогах. Первичным ключом для обоих является ItemID, который является уникальным для обеих таблиц.Mysql count records сгруппированы по дням в нескольких таблицах

В изделия находятся в таблице, которая имеет следующие поля

  • item_id
  • название
  • тела
  • date_posted

The · блоги, · таблица имеет следующий поля

  • item_id
  • название
  • тело
  • date_posted

обе таблицы имеют дополнительные поля, уникальные для них.

У меня есть третий стол, содержащий метаинформацию о статьях и сообщениях.

элементы таблица имеет следующие поля

  • item_id
  • source_id
  • ...

каждый BlogPost и статья имеет запись в таблице пунктов и записи в соответствующей таблице.

То, что я пытаюсь сделать, это построить запрос, который будет подсчитывать количество отправленных товаров в день. Я могу сделать это за одну таблицу, используя подсчет, сгруппированный по дате_поставлению, но как объединить статьи и сообщения в одном запросе?

ответ

2

Подобно Демс, но немного проще:

select date_posted, count(*) 
from (select date_posted from article union all 
     select date_posted from blogposts) v 
group by date_posted 
+0

+1: я не могу тестировать на MySQL, но при тестировании на SQL Server это очень хорошо оптимизируется (я не сделал ожидайте этого). – MatBailie

+1

*** Примечание: *** Также предполагайте, что индексы с 'date_posted' являются первым полем для оптимальной производительности. – MatBailie

0
select item_id, date_posted from blogposts where /* some conditions */ 
union all select item_id, date_posted from articles where /* some conditions */ 

Вы, вероятно, нужно положить, что в подзапрос, и если вы этого хотите, присоединиться к нему с другими таблицами, при выполнении group by. Но главное, что union - это оператор, который вы используете для объединения как данных из разных таблиц. union all сообщает базе данных, что вам не нужно, чтобы объединить повторяющиеся записи, так как вы знаете, что обе таблицы никогда не будут делиться item_id, так что это немного быстрее (возможно).

+0

Я пытался сделать союз но то, что я на самом деле пытается сделать, и это не ясно, в ФП объединить результат подсчета. поэтому два выбора: 'select count (item_id) из группы blogposts по дате' и 'select count (item_id_ из группы статей по дате – applechief

1

Я использовал бы другой дизайн таблицы для этого, с типами и подтипами. В таблице «Элементы» используется первичный ключ с одним столбцом, а ваши первичные ключи в статьях «Blog_Posts» и «Статьи» - это тот же идентификатор с внешним ключом в таблице «Элементы». Это сделало бы что-то вроде этого довольно простым, а также обеспечило бы целостность данных.

С существующей конструкции, лучше всего, вероятно, что-то вроде этого:

SELECT 
    I.item_id, 
    I.source_id, 
    COALESCE(A.date_posted, B.date_posted) AS date_posted, 
    COUNT(*) AS date_count 
FROM 
    Items I 
LEFT OUTER JOIN Articles A ON 
    A.item_id = I.item_id AND 
    I.source_id = 'A' -- Or whatever the Articles ID is 
LEFT OUTER JOIN Blog_Posts B ON 
    B.item_id = I.item_id AND 
    I.source_id = 'B' -- Or whatever the Blog_Posts ID is 
GROUP BY 
    I.item_id, 
    I.source_id, 
    COALESCE(A.date_posted, B.date_posted) 

Вы также можете попробовать с помощью UNION:

SELECT 
    SQ.item_id, 
    SQ.source_id, 
    SQ.date_posted, 
    COUNT(*) AS date_count 
FROM 
    (
     SELECT I1.item_id, I1.source_id, A.date_posted 
     FROM Items I1 
     INNER JOIN Articles A ON A.item_id = I1.item_id 
     WHERE I1.source_id = 'A' 
     UNION ALL 
     SELECT I2.item_id, I2.source_id, B.date_posted 
     FROM Items I2 
     INNER JOIN Articles B ON B.item_id = I2.item_id 
     WHERE I2.source_id = 'B' 
    ) 
3

Вы можете сделать это двумя способами.
1. Соедините все вместе, а затем соберите (см. Ответ Тома Х).
2. Совокупность каждой таблицы, СОЕДИНЕНИЕ их и агрегат снова.

Вариант 1 может казаться короче, но будет означать, что вы не можете использовать ИНДЕКСЫ в корневых таблицах (поскольку они должны быть переупорядочены для JOIN). Поэтому я покажу вариант 2, в котором вы направились в любом направлении.

SELECT 
    date_posted, 
    SUM(daily_count) AS daily_count 
FROM 
    (
    SELECT date_posted, COUNT(*) AS daily_count FROM article GROUP BY date_posted 
    UNION ALL 
    SELECT date_posted, COUNT(*) AS daily_count FROM blogposts GROUP BY date_posted 
) 
    AS combined 
GROUP BY 
    date_posted 

Это должно быть быстрым, при условии, что у вас есть индекс на каждом столе, где date_postedявляется первым поле в индексе. В противном случае таблицы будут по-прежнему нуждаться в повторной закачке для агрегации.

+0

Просто имейте в виду, что второе решение, которое некоторые агрегаты немного сложнее комбинировать. Например , средние значения.Чтобы считать, однако, это хорошее решение. –

+0

«Маленький» сложнее, да. Но если вы можете вернуть как SUM (значение), так и COUNT (*), вы можете сделать среднее. Вы даже можете сделать STDev (сумма квадратов) и т. д. Но ответ Марка Баннистера проще во всех случаях, если форматы данных подходят. – MatBailie

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