2016-02-01 4 views
0

Я пытаюсь получить COUNT (*) из объединенной таблицы «Таблица2», где даты являются обычными. PLUS - COUNT (DISTINCT (CID)) из «Table1» и сгруппированы по общему год-месяц:Получите значения COUNT() AND COUNT (DISTINCT()) для двух таблиц

Table1 
--------------- 
cid | date | 
----|---------| 
321 | 2016-01 | 
----|---------| 
423 | 2016-01 | 
----|---------| 
324 | 2016-01 | 
----|---------| 
546 | 2015-12 | 
----|---------| 

Table2 
--------------- 
id | dateEnq | 
----|---------| 
3 | 2016-01 | 
----|---------| 
6 | 2016-01 | 
----|---------| 
24 | 2015-12 | 
----|---------| 
36 | 2015-12 | 
----|---------| 

MySQL запросов:

SELECT COUNT(DISTINCT (t1.cid)) AS users, 
SUBSTR(DATE(t1.date),1,7) AS month, 
COUNT(t2.dateEnq) AS enquiries 
FROM table1 t1 
INNER JOIN table2 t2 ON SUBSTR(t2.dateEnq, 1, 7) = SUBSTR(t1.date, 1, 7) 
GROUP BY SUBSTR(DATE(t1.date),1,7) 

Это результат я получаю, но значения запросы просто способ не так, я думаю, что это не так считая значения из Таблицы 2, они должны быть как 3, 10, 25 в строке.

Как получить ежемесячный счет из Таблицы2?

users | month | enquiries| 
------|----------|----------- 
7237 | 2015-10 | 8374  | 
12597 | 2015-11 | 30066 | 
12980 | 2015-12 | 15514 | 
11305 | 2016-01 | 128169 | 

ответ

2

Ваши «счета» завышены, потому что это частичный крест продукта. В течение данного месяца каждая строка от t1 соответствует каждой строке за тот же месяц от t2.

Один из вариантов - получить подсчеты до того, как вы выполните соединение. В качестве примера, используя встроенные просмотры:

SELECT c1.users 
    , c1.month 
    , c2.enquiries 
    FROM (SELECT COUNT(DISTINCT t1.cid) AS `users` 
       , SUBSTR(DATE(t1.date),1,7) AS `month` 
      FROM table1 t1 
      GROUP BY SUBSTR(DATE(t1.date),1,7) 
     ) c1 
    JOIN (SELECT COUNT(t2.dateEnq)   AS `enquiries` 
       , SUBSTR(DATE(t2.date),1,7) AS `month` 
      FROM table2 t2 
      GROUP BY SUBSTR(DATE(t2.date),1,7) 
     ) c2 
    ON c2.month = c1.month 
ORDER BY c1.month 

Это не единственный способ (или даже обязательно является лучшим способом), чтобы получить этот результат. Существуют и другие шаблоны запросов, которые позволят получить эквивалентные результаты.

Если есть возможность иметь нулевую enquiries для данного month, то, чтобы получить, что нулевой отсчет вернулся, мы можем настроить этот запрос таким образом это внешнее соединение, а затем заменить любое значение NULL (для отсутствующего строки) с ноль во внешнем запросе:

SELECT c1.users 
    , c1.month 
    , IFNULL(c2.enquiries,0) AS `enquiries` 
    FROM (SELECT COUNT(DISTINCT t1.cid) AS `users` 
       , SUBSTR(DATE(t1.date),1,7) AS `month` 
      FROM table1 t1 
      GROUP BY SUBSTR(DATE(t1.date),1,7) 
     ) c1 
    LEFT 
    JOIN (SELECT COUNT(t2.dateEnq)   AS `enquiries` 
       , SUBSTR(DATE(t2.date),1,7) AS `month` 
      FROM table2 t2 
      GROUP BY SUBSTR(DATE(t2.date),1,7) 
     ) c2 
    ON c2.month = c1.month 
ORDER BY c1.month 
+0

А, я понимаю, что вы говорите ... ваш первый запрос работает отлично. – Grant

+0

Да, есть возможность 0, спасибо, что тоже отлично работает. – Grant

+1

... Я мог бы объяснить ... потому что запросы встроенного представления гарантированно имеют уникальные значения 'month' (из-за предложения GROUP BY), соединение между ними будет иметь (не более) одну строку каждый за данный месяц. Таким образом, подсчеты не будут завышены. Вы можете запускать запросы встроенного просмотра отдельно для тестирования. Как только вы понимаете, как исходный запрос генерирует раздутые счета, вопрос в том, как я могу написать инструкцию SQL, которая не генерирует частичный кросс-продукт. Это всего лишь пример одного подхода. Вы можете оставить вопрос открытым и посмотреть, получите ли вы лучший ответ. – spencer7593