2010-05-06 4 views
2

У меня есть кампания с таблицей, в которой есть сведения о отправляемых почтовых сообщениях.Как написать этот запрос, используя соединения?

campaign_table: campaign_id campaign_name flag 
         1   test1  1 
         2   test2  1 
         3   test3  0 

другая деятельность в кампаниях с таблетками, которая содержит информацию о деятельности кампании.

campaign_activity: campaign_id is_clicked is_opened 
          1    0   1   
          1    1   0   
          2    0   1 
          2    1   0 

Я хочу, чтобы все кампании со значением 3 флага и числа is_clicked столбцов со значением 1 и числом столбцов с is_opened значением 1 в одном запросе.

ie. campaign_id campaign_name numberofclicks numberofopens 
      1   test1   1    1 
      2   test2   1    1 

Я сделал это с помощью вложенного запроса с запросом:

select c.campaign_id,c.campaign_name, 
(SELECT count(campaign_id) from campaign_activity WHERE campaign_id=c.id AND is_clicked=1) as numberofclicks, 
(SELECT count(campaign_id) from campaign_activity WHERE campaign_id=c.id AND is_clicked=1) as numberofopens 
FROM 
campaign c 
WHERE c.flag=1 

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

+0

Его обычно нормально использовать подзапросы в выражении WHERE, но не использовать их в качестве столбцов. –

ответ

4

Это должно сделать трюк. Замените INNER JOIN для LEFT OUTER JOIN, если вы хотите включить кампании, которые не имеют активности.

SELECT 
    c.Campaign_ID 
    , c.Campaign_Name 
    , SUM(CASE WHEN a.Is_Clicked = 1 THEN 1 ELSE 0 END) AS NumberOfClicks 
    , SUM(CASE WHEN a.Is_Opened = 1 THEN 1 ELSE 0 END) AS NumberOfOpens 
FROM 
    dbo.Campaign c 
INNER JOIN 
    dbo.Campaign_Activity a 
ON a.Campaign_ID = c.Campaign_ID 
GROUP BY 
    c.Campaign_ID 
    , c.Campaign_Name 
+0

'CASE WHEN a.Is_XXXX <> 0 THEN 1 ELSE 0 END' может быть лучшей идеей, все ненулевые значения возвращают 1, ноль и NULL возвращают 0. –

+0

Nice; с этим оператором 'case' вы также можете легко изменить' inner join' в 'left external join', чтобы поймать кампании, которые не имеют записей в таблице действий. – tzaman

+0

@Salman: Технически OP специально запросил подсчет столбцов со значением 1, а не отличным от нуля/null, так что это правильно. – tzaman

0

Я предполагаю, что это следует сделать это:

select * from campaign_table inner join campaign_activity on campaign_table.id = campaign_activity.id where campaign_table.flag = 3 and campaign_activity.is_clicked = 1 and campaign_activity.is_opened = 1 

Attn: это не испытывается в реальной ситуации

+0

Я хочу получить счет is_clicked и is_opened, имея значения 1. не только столбцы. – aquero

2

Мда. Это то, что вы хотите так просто, как это? Я не уверен, что я читаю право вопрос ...

SELECT 
    campaign_table.campaign_id, SUM(is_clicked), SUM(is_opened) 
FROM 
    campaign_table 
    INNER JOIN campaign_activity ON campaign_table.campaign_id = campaign_activity.campaign_id 
WHERE 
    campaign_table.flag = 1 
GROUP BY 
    campaign_table.campaign_id 

Обратите внимание, что с INNER JOIN здесь, вы не увидите кампании, где нет ничего, что соответствует в таблице campaign_activity. В этом случае вы должны использовать LEFT JOIN и преобразовать NULL в 0 в SUM, например. SUM (IFNULL (is_clicked, 0)).

4

Предполагая is_clicked и is_opened не только когда 1 или 0, это должно работать:

select c.campaign_id, c.campaign_name, sum(d.is_clicked), sum(d.is_opened) 
from campaign c inner join campaign_activity d 
on c.campaign_id = d.campaign_id 
where c.flag = 1 
group by c.campaign_id, c.campaign_name 

Нет подзапросы.

+1

И если 'is_clicked' и' is_opened' не являются только 1 или 0, вы можете использовать 'SUM (IF (is_clicked = 1,1,0))' –

+0

@Draco: Приятная настройка! – tzaman

+0

Возможно, вы захотите использовать 'left join' для извлечения даже тех кампаний, у которых нет соответствующей активности; для таких строк столбцы 'SUM' будут содержать' NULL'. –

0

SQL, в его простейшей форме и наиболее надежная форма заключается в следующем: (отформатирован для удобства чтения)

SELECT 
campaign_table.campaign_ID, campaign_table.campaign_name, Sum(campaign_activity.is_clicked) AS numberofclicks, Sum(campaign_activity.is_open) AS numberofopens 

FROM 
campaign_table INNER JOIN campaign_activity ON campaign_table.campaign_ID = campaign_activity.campaign_ID 

GROUP BY 
campaign_table.campaign_ID, campaign_table.campaign_name, campaign_table.flag 

HAVING 
campaign_table.flag=1; 
Смежные вопросы