例如有这样的结构:
CREATE TABLE clicks
(`date` varchar(50), `sum` int, `id` int)
;
CREATE TABLE marks
(`click_id` int, `name` varchar(50), `value` varchar(50))
;
其中点击可以有很多标记
示例数据:
INSERT INTO clicks
(`sum`, `id`, `date`)
VALUES
(100, 1, '2017-01-01'),
(200, 2, '2017-01-01')
;
INSERT INTO marks
(`click_id`, `name`, `value`)
VALUES
(1, 'utm_source', 'test_source1'),
(1, 'utm_medium', 'test_medium1'),
(1, 'utm_term', 'test_term1'),
(2, 'utm_source', 'test_source1'),
(2, 'utm_medium', 'test_medium1')
;
我需要获得按date
分组的点击值,其中包含所有选定的值。
我提出要求:
select
c.date,
sum(c.sum)
from clicks as c
left join marks as m ON m.click_id = c.id
where
(m.name = 'utm_source' AND m.value='test_source1') OR
(m.name = 'utm_medium' AND m.value='test_medium1') OR
(m.name = 'utm_term' AND m.value='test_term1')
group by date
并获得2017-01-01 = 700,但我想获得100,这意味着只有点击1有所有标记。 或者如果条件是
(m.name = 'utm_source' AND m.value='test_source1') OR
(m.name = 'utm_medium' AND m.value='test_medium1')
我需要300而不是600
我找到了通过第一个查询得到明显的click_id,然后按条件whereIn对日期和日期进行求和的答案,但是对于非常大且具有id作为uuid的真实数据库,此请求执行时间过长。任何建议如何让它正常工作?
答案 0 :(得分:1)
您可以使用以下查询来实现:
当有三个条件时,您必须通过HAVING count(*) >= 3
SELECT cc.DATE
,sum(cc.sum)
FROM clicks AS cc
INNER JOIN (
SELECT id
FROM clicks AS c
LEFT JOIN marks AS m ON m.click_id = c.id
WHERE (
m.NAME = 'utm_source'
AND m.value = 'test_source1'
)
OR (
m.NAME = 'utm_medium'
AND m.value = 'test_medium1'
)
OR (
m.NAME = 'utm_term'
AND m.value = 'test_term1'
)
GROUP BY id
HAVING count(*) >= 3
) AS t ON cc.id = t.id
GROUP BY cc.DATE
当有三个条件时,您必须通过HAVING count(*) >= 2
SELECT cc.DATE
,sum(cc.sum)
FROM clicks AS cc
INNER JOIN (
SELECT id
FROM clicks AS c
LEFT JOIN marks AS m ON m.click_id = c.id
WHERE (
m.NAME = 'utm_source'
AND m.value = 'test_source1'
)
OR (
m.NAME = 'utm_medium'
AND m.value = 'test_medium1'
)
GROUP BY id
HAVING count(*) >= 2
) AS t ON cc.id = t.id
GROUP BY cc.DATE
演示:http://sqlfiddle.com/#!9/fe571a/35
希望这对你有用......
答案 1 :(得分:1)
您获得700,因为联接会为不同的ID生成多行。 mark
表格中有3行ID=1
和sum=100
,并且有两行ID=2
和sum=200
。在执行join时,其中3行sum = 100,2行sum = 200,所以添加这些和得到700.要解决这个问题,你必须在click_id上聚合,如下图所示:
select
c.date,
sum(c.sum)
from clicks as c
inner join (select * from marks where (name = 'utm_source' AND
value='test_source1') OR (name = 'utm_medium' AND value='test_medium1')
OR (name = 'utm_term' AND value='test_term1')
group by click_id) as m
ON m.click_id = c.id
group by c.date;
<强> DEMO SQL FIDDLE 强>
答案 2 :(得分:1)
我自己找到了正确的方法,它可以处理大量数据 主要目标是使请求生成一个包含子查询(条件)的表,这些表不依赖于结果中的数据量,因此最好的方法是:
exp(c * ln(b))
因此,我们需要根据我们的许多条件进行多次连接