我是一个做一个小项目的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 JOIN
和Impressions
之间进行了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
,表的顺序不会影响结果集。