我是一个做一个小项目的mySQL新手。我将尽全力描述问题的全部内容,以便专业人员可以不仅在代码方面,而且在概念上帮助我。我以前从未做过sql,但已经在Python,Matlab等(过程环境)中进行了编程。无需再费周折,

以下代码非常慢,并且if语句

if (carts.staffId ='', 'UNASSISTED', 'ASSITED') as EXPERIENCE


因为它总是像UNASSISTED一样不起作用。知道为什么它不起作用吗?

这是代码

select
    Impressions.session_id,
    sum(if(Impressions.impressionAction = 'SENDMAIL', 1, 0)) as EMAIL,
    count(if(Impressions.impressionAction = 'TAPPED', 1, NULL)) as SCANS,
    TIMESTAMPDIFF(SECOND, min(Impressions.createDate), max(Impressions.createDate)) AS Duration,

    if (carts.staffId ='', 'UNASSISTED', 'ASSITED') as EXPERIENCE
    from Impressions, carts
    where Impressions.session_id in (select carts.session_id from carts where carts.session_id <> '' )
    group by Impressions.session_id;


职员表中的staffId列存在。我想要的只是从购物车中staffId的条件中提取输出,以将其添加到表印象数列中

本质上,我正在尝试从子查询中添加一列,并将其添加到主查询的主列的末尾

更新:我将问题分为两部分,这是代码的样子。本质上,两个输出之间的UNION会创建所需的最终输出。我只需要一口气:

/***********************ASSISTED*******************************/
select  session_id,
    sum(if(impressionAction = 'SENDMAIL', 1, 0)) as EMAIL,
    count(if(impressionAction = 'TAPPED', 1, NULL)) as SCANS,
    TIMESTAMPDIFF(SECOND, min(createDate), max(createDate)) AS Duration
from Impressions
where session_id in
    (select session_id
    from carts
    where session_id <> '' AND staffId <> '' AND staffId <>'ollie' AND staffId<> 'Laura')
        AND createDate >= '2014-06-23'AND createDate < '2014-06-30'
        AND HOUR(createDate) >= 10 AND HOUR(createDate) < 21
        AND impressionId NOT LIKE '%made.com' AND impressionId NOT LIKE '%cloudtags.com%'
group by session_id;



/***************************UNASSISTED***********************/
...everything is same...
    where session_id <> '' AND staffId = '' OR staffId ='ollie' OR staffId= 'Laura' )
...;


第二次更新
ASSISTTED vs UNASSISTED情况下,我还没有提及其他约束。除了在此处过滤掉那些内容外,我还需要从与productId = 1902关联的表products中过滤掉cartID

最佳答案

您在CROSS JOINImpressions之间进行了carts操作。 (是的,您的查询正在执行JOIN操作,它只是使用旧式逗号语法来指定JOIN操作。)

这是一个CROSS JOIN,因为没有谓词可以使两个表之间的行“匹配”。 Impressions中的每一行都与carts中的每一行匹配。

您有一个GROUP BY子句将所有从“ cc”中“匹配”的行折叠为单行。 MySQL仅从carts中的单行中选择值。并且它为carts中的每一行从carts中选择完全相同的行。

看起来您想使用Impressions列中的值将carts中的行与Impressions中的行“匹配”。

像这样:

SELECT i.session_id
     , SUM(IF(i.impressionAction = 'SENDMAIL', 1, 0)) AS EMAIL
     , COUNT(IF(i.impressionAction = 'TAPPED', 1, NULL)) AS SCANS
     , TIMESTAMPDIFF(SECOND, MIN(i.createDate), MAX(i.createDate)) AS Duration
     , MIN(IF(c.staffId = '', 'UNASSISTED', 'ASSISTED')) AS EXPERIENCE
 FROM Impressions i
 JOIN carts c
   ON c.session_id = i.session_id
  AND c.session_id <> ''
GROUP
   BY i.session_id


如果session_id中有多行具有相同的匹配carts。 MySQL将只选择一行,并评估session_id表达式。 (或者,将对每一行评估该表达式,然后选择要返回的结果值之一。

该IF表达式正在测试IF(c.staff_id等于零长度的字符串(如果staff_id是数字,则文字staff_id将被评估为''的数值...但是我们只是在猜测(0的实际数据类型。)如果该行上的staff_id的值为staff_id,则该值将不等于空字符串。

我怀疑(但不知道您的用例,因此只是一个猜测),如果与session_id相关的任何NULL输入了staff_id,则该会话被视为“辅助”的,您希望返回“ ASSISTED”。也就是说,仅当carts均未填充staff_id时,您才想返回“ UNASSISTED”。为此,我将IF表达式包装在MIN()聚合函数中。



编辑

根据添加到问题的查询,我将执行以下操作:

SELECT i.session_id
     , SUM(IF(i.impressionAction = 'SENDMAIL', 1, 0)) AS EMAIL
     , COUNT(IF(i.impressionAction = 'TAPPED', 1, NULL)) AS SCANS
     , TIMESTAMPDIFF(SECOND, MIN(i.createDate), MAX(i.createDate)) AS Duration
     , MIN(IF(c.staffId IN ('','ollie','Laura'), 'UNASSISTED', 'ASSISTED')) AS EXPERIENCE
  FROM Impressions i
  JOIN carts c
    ON c.session_id <> ''
   AND c.session_id = i.session_id
 WHERE i.createDate >= '2014-06-23'
   AND i.createDate < '2014-06-30'
   AND HOUR(i.createDate) >= 10
   AND HOUR(i.createDate) < 21
   AND i.impressionId NOT LIKE '%made.com'
   AND i.impressionId NOT LIKE '%cloudtags.com%'
 GROUP
    BY i.session_id;


请注意,如果carts列具有staff_id值,则IF表达式将返回“ ASSISTED”,因为NULL将不等于任何列出的值。为了解决这个问题,以便将NULL视为UNASSISTED,我们可以使用NULL

     , MIN(IF(c.staffId NOT IN ('','ollie','Laura'), 'ASSISTED', 'UNASSISTED')) AS EXPERIENCE


同样,如果NOT IN中没有(至少一个)对应行,则查询将不返回Impressions中的任何行。

如果我们想从carts返回行,即使OUTER JOIN中没有匹配的行,也可以指定Impressions。我们可以通过在carts关键字之前添加关键字LEFT来指定。请注意,如果我们确实添加了外部联接,则在JOIN中找不到匹配的行时,staff_id列将为NULL。 (我们只想确保在IF表达式中适当地处理了潜在的carts值。)

后续注意事项

如果我们要从NULL返回的行中没有LEFT [OUTER] JOIN且没有Impressions的行,则只需要session_id

如果我们对carts中出现的每个carts总是在session_id中有一行,则您Impressions就足够了。即使在“右侧”的表/行中找不到匹配的行,也可以联接。这些表的顺序实际上仅取决于[INNER] JOIN,即哪个表应位于“左侧”。使用LEFT JOIN,表的顺序不会影响结果集。

10-05 19:44