2011-12-20 4 views
3

Я использую две таблицы в базе данных. Первый содержит данные, относящиеся к успешным и неуспешным платежам, а во второй таблице приведены данные о статусе услуг.Запрос внутреннего соединения Mysql

Результат запроса должен объединить обе таблицы, а в результате списка - успешные и неуспешные платежи, сгруппированные по дням, а также статус услуг, сгруппированных по дням.

Первая таблица выглядит следующим образом:

id | charged | date 
----------------------------- 
8 | OK  | 2011-12-03 
7 | OK  | 2011-12-03 
9 | NO  | 2011-12-03 
11 | OK  | 2011-12-04 
14 | NO  | 2011-12-04 

Вторая таблица выглядит следующим образом:

id | status | date 
-------------------------- 
8 | 1 | 2011-12-03 
9 | 1 | 2011-12-03 
11 | 0 | 2011-12-04 
12 | 0 | 2011-12-04 
14 | 1 | 2011-12-04 

Правильный результат запроса должен быть:

date | not_charged | charged | status_1 | status_0 
----------------------------------------------------------- 
2011-12-04 |  1  | 1  | 1  | 2 
2011-12-03 |  1  | 2  | 2  | 0 

Запрос, который я пытался выглядит следующим образом:

SELECT i.date, SUM(
CASE WHEN i.charged = 'NO' 
THEN 1 ELSE 0 END) AS not_charged, SUM(
CASE WHEN i.charged = 'OK' 
THEN 1 ELSE 0 END) AS charged, SUM(
CASE WHEN s.status = '1' 
THEN 1 ELSE 0 END) AS status_1, SUM(
CASE WHEN s.status = '0' THEN 1 ELSE 0 END) AS status_0 
FROM charge i INNER JOIN status s ON s.date = i.date 
GROUP BY i.date 

Но я получаю неправильный результат, который выглядит, как этот

date | not_charged | charged | status_1 | status_0 
--------------------------------------------------------- 
2011-12-04 |  3  | 3 | 2  | 4 
2011-12-03 |  2  | 4 | 6  | 0 

Что я делаю неправильно и как я могу получить правильный результат?

Спасибо за все предложения.

ответ

1

Попробуйте один -

SELECT date, 
    SUM(IF(charged = 'NO', 1, 0)) not_charged, 
    SUM(IF(charged = 'OK', 1, 0)) charged, 
    SUM(IF(status = 1, 1, 0)) status_1, 
    SUM(IF(status = 0, 1, 0)) status_0 
FROM (
    SELECT date, charged, NULL status FROM charge 
    UNION ALL 
    SELECT date, NULL charged, status FROM status 
    ) t 
    GROUP BY date DESC; 

+------------+-------------+---------+----------+----------+ 
| date  | not_charged | charged | status_1 | status_0 | 
+------------+-------------+---------+----------+----------+ 
| 2011-12-04 |   1 |  1 |  1 |  2 | 
| 2011-12-03 |   1 |  2 |  2 |  0 | 
+------------+-------------+---------+----------+----------+ 
+0

+1: Самый краткий вариант, если записи не нуждаются в их идентификаторах. – MatBailie

1

Это предполагает ID столбцы, связанные что состояние службы и статус платежа вместе ...

SELECT 
    COALESCE(charge.date, status.date)      AS date, 
    SUM(CASE WHEN charge.charged = 'NO' THEN 1 ELSE 0 END) AS not_charged, 
    SUM(CASE WHEN charge.charged = 'OK' THEN 1 ELSE 0 END) AS charged, 
    SUM(CASE WHEN status.status = '0' THEN 1 ELSE 0 END) AS status_0, 
    SUM(CASE WHEN status.status = '1' THEN 1 ELSE 0 END) AS status_1 
FROM 
    charge 
FULL OUTER JOIN 
    status 
    ON charge.id = status.id 
GROUP BY 
    COALESCE(charge.date, status.date) 

Обратите внимание, я отметить уверены, как вы хотите иметь дело с 7 (Нет статус записи) и 12 (нет плата запись). Это в настоящее время просто считается, что есть.


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

В настоящее время вы получаете это, потому что вы только относятся по дате ...

id | charged | date   id | status | date 
----------------------------- -------------------------- 
8 | OK  | 2011-12-03  8 | 1 | 2011-12-03 
8 | OK  | 2011-12-03  9 | 1 | 2011-12-03 

7 | OK  | 2011-12-03  8 | 1 | 2011-12-03 
7 | OK  | 2011-12-03  9 | 1 | 2011-12-03 

9 | NO  | 2011-12-03  8 | 1 | 2011-12-03 
9 | NO  | 2011-12-03  9 | 1 | 2011-12-03 

11 | OK  | 2011-12-04  11 | 0 | 2011-12-04 
11 | OK  | 2011-12-04  12 | 0 | 2011-12-04 
11 | OK  | 2011-12-04  14 | 1 | 2011-12-04 

14 | NO  | 2011-12-04  11 | 0 | 2011-12-04 
14 | NO  | 2011-12-04  12 | 0 | 2011-12-04 
14 | NO  | 2011-12-04  14 | 1 | 2011-12-04 


Вместо этого вам необходимо консолидировать данные до 1 на сегодняшний день за столом, затем присоединяются ...

SELECT 
    COALESCE(charge.date, status.date) AS date, 
    charge.not_charged, 
    charge.charged, 
    status.status_0, 
    status.status_1 
FROM 
    (
    SELECT 
    date, 
    SUM(CASE WHEN charged = 'NO' THEN 1 ELSE 0 END) AS not_charged, 
    SUM(CASE WHEN charged = 'OK' THEN 1 ELSE 0 END) AS  charged 
    FROM 
    charge 
    GROUP BY 
    date 
) 
    AS charge 
FULL OUTER JOIN 

    (
    SELECT 
    date, 
    SUM(CASE WHEN charged = '0' THEN 1 ELSE 0 END) AS status_0, 
    SUM(CASE WHEN charged = '1' THEN 0 ELSE 1 END) AS status_1 
    FROM 
    status 
    GROUP BY 
    date 
) 
    AS status 
    ON charge.date = status.date 

Есть и другие методы, но, надеюсь, это немного объясняет вам.

0

Я предлагаю использовать UNION ALL:

select date, 
     coalesce(sum(not_charged),0) not_charged, 
     coalesce(sum(charged),0) charged, 
     coalesce(sum(status_1),0) status_1, 
     coalesce(sum(status_0),0) status_0 
from (select date, 
      case charged when 'NO' then 1 end not_charged, 
      case charged when 'OK' then 1 end charged, 
      0 status_1, 
      0 status_0 
     from charge 
     union all 
     select date, 
      0 not_charged, 
      0 charged, 
      case status when '1' then 1 end status_1, 
      case status when '0' then 1 end status_0 
     from status) sq 
group by date 
+0

предварительно агрегирование бы до UNION, а также после того, как, за исключением каких-либо затрат ресурсов? – MatBailie

+0

Не так далеко, насколько я знаю. Я бы ожидал (очень) незначительного повышения производительности, так как одни и те же данные были бы агрегированы дважды, хотя я подозреваю, что фактическое различие будет слишком маленьким, чтобы сказать. –

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