我目前有一个跟踪销售团队销售情况的数据库。我有一个查询,将拉动每个推销员及其相关的总数,但我希望按周分解,然后如果可能的话,在一周内汇总显示。
我目前使用的查询是:
SELECT ROUND(SUM(n.newBalance), 2) AS newB, u.username
FROM (
SELECT
j.leadid AS custid,
WEEK(j.convertdate) AS weeks,
j.price / (SELECT count(*) FROM assignmentstbl a WHERE a.custid=j.leadid) AS newBalance
FROM jobbooktbl j
WHERE j.convertdate BETWEEN '2017-01-02' AND '2017-07-31'
AND j.status IN (4,6,7,8,11)
) n
JOIN assignmentstbl a USING (custid)
JOIN usertbl u USING (userid)
GROUP BY a.userid
返回以下内容(由Salesman分组):
+-----------+-------------+
| salesman | Sales Total |
+-----------+-------------+
| salesman1 | 1850 |
| salesman2 | 1170 |
+-----------+-------------+
我希望完成的是按周分解并返回以下内容(按星期分组然后由销售员分组):
+-----------+--------+-------------+
| salesman | weekNo | sales total |
+-----------+--------+-------------+
| salesman1 | 1 | 0 |
| salesman2 | 1 | 0 |
| salesman1 | 2 | 100 |
| salesman2 | 2 | 100 |
| salesman1 | 3 | 1300 |
| salesman2 | 3 | 0 |
| salesman1 | 4 | 450 |
| salesman2 | 4 | 1070 |
| salesman1 | 5 | 0 |
| salesman2 | 5 | 0 |
+-----------+--------+-------------+
如果可能的话,聚合也是这样的(由销售人员按周运行总计/聚合分组):
+-----------+--------+-------------+
| salesman | weekNo | sales total |
+-----------+--------+-------------+
| salesman1 | 1 | 0 |
| salesman2 | 1 | 0 |
| salesman1 | 2 | 100 |
| salesman2 | 2 | 100 |
| salesman1 | 3 | 1400 |
| salesman2 | 3 | 100 |
| salesman1 | 4 | 1850 |
| salesman2 | 4 | 1170 |
| salesman1 | 5 | 1850 |
| salesman2 | 5 | 1170 |
+-----------+--------+-------------+
到目前为止,这是架构:
CREATE TABLE weekstbl
(`weekNo` int, `weekStart` date)
;
INSERT INTO weekstbl
(`weekNo`, `weekStart`)
VALUES
(1, '2017-01-02'),
(2, '2017-01-09'),
(3, '2017-01-16'),
(4, '2017-01-23'),
(5, '2017-01-30')
;
CREATE TABLE jobbooktbl
(`leadid` int, `convertdate` date, `price` int, `status` int)
;
INSERT INTO jobbooktbl
(`leadid`, `convertdate`, `price`, `status`)
VALUES
(1, '2017-01-16', 500, 4),
(2, '2017-01-24', 620, 6),
(3, '2017-01-17', 800, 7),
(4, '2017-01-26', 900, 11),
(5, '2017-01-10', 200, 4)
;
CREATE TABLE assignmentstbl
(`custid` int, `userid` int)
;
INSERT INTO assignmentstbl
(`custid`, `userid`)
VALUES
(1, 1),
(2, 2),
(3, 1),
(4, 2),
(4, 1),
(5, 1),
(5, 2)
;
CREATE TABLE usertbl
(`userid` int, `username` varchar(25))
;
INSERT INTO usertbl
(`userid`,`username`)
VALUES
(1,'salesman1'),
(2,'salesman2')
;
以下是SQLFIDDLE,其中包含上述所有信息。
我试过LEFT JOIN这两张桌子,但无济于事。我真的是SQL的初学者,所以这有点离开我的轮子。我也是因为我不知道如何在没有任何销售员价值的几个星期内返回0来创建周末,这可能没有必要。
试验:
试验1
SELECT ROUND(SUM(n.newBalance), 2) AS newB, weeks, u.username
FROM (
SELECT
j.leadid AS custid,
w.weekno AS weeks,
j.price / (SELECT count(*) FROM assignmentstbl a WHERE a.custid=j.leadid) AS newBalance
FROM jobbooktbl j
LEFT JOIN weekstbl w on w.weekNo=WEEK(j.convertdate)
AND j.convertdate BETWEEN '2017-01-02' AND '2017-07-31'
AND j.status IN (4,6,7,8,11)
) n
JOIN assignmentstbl a USING (custid)
JOIN usertbl u USING (userid)
GROUP BY weeks, a.userid
这返回了以下结果集,其中不包括第3周(对于salesman2)或5的0:
+-----------+--------+-------------+
| salesman | weekNo | sales total |
+-----------+--------+-------------+
| salesman1 | 2 | 100 |
| salesman2 | 2 | 100 |
| salesman1 | 3 | 1300 |
| salesman1 | 4 | 450 |
| salesman2 | 4 | 1070 |
+-----------+--------+-------------+
试验2
SELECT ROUND(SUM(n.newBalance), 2) AS newB, weeks, u.username
FROM (
SELECT
j.leadid AS custid,
w.weekno AS weeks,
j.price / (SELECT count(*) FROM assignmentstbl a WHERE a.custid=j.leadid) AS newBalance
FROM jobbooktbl j
join weekstbl w on j.convertdate between weekstart and date(weekstart + interval 6 day )
WHERE j.convertdate BETWEEN '2017-01-02' AND '2017-07-31'
AND j.status IN (4,6,7,8,11)
) n
JOIN assignmentstbl a USING (custid)
JOIN usertbl u USING (userid)
GROUP BY weeks, a.userid
这返回了以下结果集(第1,3周(针对salesman2)或5)不包括0:
+-----------+--------+-------------+
| salesman | weekNo | sales total |
+-----------+--------+-------------+
| salesman1 | 2 | 100 |
| salesman2 | 2 | 100 |
| salesman1 | 3 | 1300 |
| salesman1 | 4 | 450 |
| salesman2 | 4 | 1070 |
+-----------+--------+-------------+
试验3:
SELECT * FROM (
SELECT ROUND(SUM(n.newBalance), 2) AS newB, u.username,weeks
FROM (
SELECT
j.leadid AS custid,
WEEK(j.convertdate) AS weeks,
j.price / (SELECT count(*) FROM assignmentstbl a WHERE a.custid=j.leadid) AS newBalance
FROM jobbooktbl j
WHERE j.convertdate BETWEEN '2017-01-02' AND '2017-07-31'
AND j.status IN (4,6,7,8,11)
) n
JOIN assignmentstbl a USING (custid)
JOIN usertbl u USING (userid)
GROUP BY a.userid,n.weeks
ORDER BY newB DESC
)INNERTABLE
LEFT JOIN weekstbl CL ON CL.weekNo=INNERTABLE.weeks
这返回了以下结果集(第1,3周(针对salesman2)或5)不包括0:
+-----------+--------+-------------+
| salesman | weekNo | sales total |
+-----------+--------+-------------+
| salesman1 | 2 | 100 |
| salesman2 | 2 | 100 |
| salesman1 | 3 | 1300 |
| salesman1 | 4 | 450 |
| salesman2 | 4 | 1070 |
+-----------+--------+-------------+
试验4:
与此相近一点
SELECT
w.weekNo, COALESCE(ROUND(SUM(n.newBalance), 2),0) AS newB, n.username
FROM
weekstbl w
LEFT JOIN (
SELECT
j.leadid AS custid,
j.convertdate AS sold,
u.username AS username,
j.price / (SELECT count(*) FROM assignmentstbl a WHERE a.custid=j.leadid) AS newBalance
FROM
jobbooktbl j
JOIN assignmentstbl a ON j.leadid = a.custid
JOIN usertbl u ON u.userid = a.userid
) n
ON
w.weekNo = WEEK(n.sold)
GROUP BY
n.username, w.weekNo
ORDER BY
w.weekNo
这返回了以下结果集(第1周和第5周返回0,但没有识别推销员,并且在第3周没有为salesman2返回0):
+-----------+--------+-------------+
| salesman | weekNo | sales total |
+-----------+--------+-------------+
| (null) | 1 | 0 |
| salesman1 | 2 | 100 |
| salesman1 | 2 | 100 |
| salesman1 | 3 | 1300 |
| salesman1 | 4 | 450 |
| salesman2 | 4 | 1070 |
| (null) | 5 | 0 |
+-----------+--------+-------------+
答案 0 :(得分:1)
我在weekstbl中添加了一个联接。你可以查看下面的查询。我希望这有帮助。
SELECT ROUND(SUM(n.newBalance), 2) AS newB, weeks, u.username
FROM (
SELECT
j.leadid AS custid,
w.weekno AS weeks,
j.price / (SELECT count(*) FROM assignmentstbl a WHERE a.custid=j.leadid) AS newBalance
FROM jobbooktbl j
join weekstbl w on j.convertdate between weekstart and date(weekstart + interval 6 day )
WHERE j.convertdate BETWEEN '2017-01-02' AND '2017-07-31'
AND j.status IN (4,6,7,8,11)
) n
JOIN assignmentstbl a USING (custid)
JOIN usertbl u USING (userid)
-- WHERE a.userid=5
GROUP BY weeks, a.userid
ORDER BY newB DESC
这是一个更新的答案。
select userid, username, week, year, fvalue
from ( select sub3.*,
if(@previous = userid, @value1 := @value1 + value, @value1 := value ) fvalue,
@previous := userid
from (select distinct ut.userid, ut.username,
week(date) as week,year(date) as year ,coalesce(sub2.newB,0) as value
from ( SELECT (CURDATE() - INTERVAL c.number DAY) AS date
FROM (SELECT singles + tens + hundreds number FROM
( SELECT 0 singles
UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
) singles JOIN
(SELECT 0 tens
UNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30
UNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60
UNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90
) tens JOIN
(SELECT 0 hundreds
UNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300
UNION ALL SELECT 400 UNION ALL SELECT 500 UNION ALL SELECT 600
UNION ALL SELECT 700 UNION ALL SELECT 800 UNION ALL SELECT 900
) hundreds
ORDER BY number DESC) c ) abc
cross join usertbl ut
left join (
SELECT ROUND(SUM(n.newBalance), 2) AS newB, weeks, years,a.userid, u.username
FROM (
SELECT
j.leadid AS custid,
w.weekno AS weeks,
year(weekstart) as years,
j.price / (SELECT count(*) FROM assignmentstbl a WHERE a.custid=j.leadid) AS newBalance
FROM jobbooktbl j
join weekstbl w on j.convertdate between weekstart and date(weekstart + interval 6 day )
WHERE j.convertdate BETWEEN '2017-01-02' AND '2017-07-31'
AND j.status IN (4,6,7,8,11)
) n
JOIN assignmentstbl a USING (custid)
JOIN usertbl u on u.userid = a.userid
GROUP BY weeks, a.userid
) sub2 on sub2.userid = ut.userid
and weeks = week(date)
and years = year(date)
where date between '2017-01-02' AND '2017-07-31'
order by userid,year(date), week(date) ) sub3 ) sub4
order by year, week, userid
注意:我建议创建dim_time表,它存储日期的所有相关信息。
说明:
1)子查询名称:abc 这将根据您的输入生成周和年。之后用usertbl交叉加入你的结果。你想要的那么多行 最终输出。现在我们根据您的要求添加值。
2)子查询名称:sub2
这会产生您所需的结果,但它没有显示0值。
3)现在1离开加入2 这会给你结果(按星期分组然后由销售员分组)。更改order by子句只是为了获得预期的输出 这成为你的sub3。这是必要的,因为我们必须将前一个值加到下一个值。
4)创建varialbe @previous和@ value1 因为我们已根据用户标识对结果进行了排序。现在第一行来了,它检查下面的条件。然后它转到其他部分,因为它不匹配, 将用户标识存储在@previous中。现在它会占用第二行,它会将前一个值添加到下一行,因为条件已满足。相似它会添加 你的结果,直到新用户ID来。
Condtion:
MySQL (@previous = userid, @value1 := @value1 + value ,@value1 := value)
if @previous = userid
then @value1 := @value1 + value
else @value1 := value;
我希望这会有所帮助。
答案 1 :(得分:0)
SELECT * FROM (
SELECT ROUND(SUM(n.newBalance), 2) AS newB, u.username,weeks
FROM (
SELECT
j.leadid AS custid,
WEEK(j.convertdate) AS weeks,
j.price / (SELECT count(*) FROM assignmentstbl a WHERE a.custid=j.leadid) AS newBalance
FROM jobbooktbl j
WHERE j.convertdate BETWEEN '2017-01-02' AND '2017-07-31'
AND j.status IN (4,6,7,8,11)
) n
JOIN assignmentstbl a USING (custid)
JOIN usertbl u USING (userid)
GROUP BY a.userid,n.weeks
ORDER BY newB DESC
)INNERTABLE
LEFT JOIN CALENDAR CL ON CL.WEEK=INNERTABLE.weeks
您可以尝试以上查询。
现在使用Calendar Table创建一个日历表。
使用上面的查询并使用日历表进行连接,您可以实现您想要的效果。表示该周没有条目的记录的0值。