2017-08-01 59 views
3

我目前有一个数据库,用于跟踪销售团队的销售情况。我有一个查询,将拉动每个推销员和他们相关的总数,但我希望这一周有这个细分,然后如果可能的话在一周内显示这一点。MYSQL与销售人员和星期加入星期表

我使用当前的查询是:

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 | 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所有上述的信息。

我试过左加入两个表,但无济于事。我真的是SQL的初学者,所以这有点不在我的车轮之中。我也在创建weekstbl,只是因为我不知道如何在没有任何推销员价值的几周内返回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 

这返回以下结果集,其不包括0的用于周数1 3(用于salesman2)或5:

+-----------+--------+-------------+ 
| 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 

这返回以下结果集(不包括0的数周1,3(对于salesman2),或5):

+-----------+--------+-------------+ 
| 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 

这将返回以下结果集合(不包括0的数周1,3(对于salesman2),或5):

+-----------+--------+-------------+ 
| 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 

这将返回以下结果集(返回0的数周1和5,但不承认业务员和salesman2第3周没有回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  | 
+-----------+--------+-------------+ 

回答

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子句。
这成为你的子3。这是必要的,因为我们必须将先前的值累加到下一个值。

4)Create varialbe @previous and @ value1 由于我们已经根据用户标识对结果进行了排序。现在第一行来检查下面的情况。然后它转到其他部分,因为它不匹配, 在@previous中存储用户标识。它现在执行第二行,因为条件满足,它会将前一个值添加到下一行。相似的,它会添加 你的结果,直到新的用户名来。

Condtion:

MySQL (@previous = userid, @value1 := @value1 + value ,@value1 := value) 

if @previous = userid 
then @value1 := @value1 + value 
else @value1 := value; 

我希望这将有助于。

+0

这是返回'[['salesman1',100],['salesman2',100],['salesman1',1300],['salesman2',1070],['salesman1',450]]'这是缺少0。 –

+0

意味着它应该显示所有星期值。对于您选择的输入应该有多少个0。 –

+0

我已经更新了这个问题,包括一个更好的结果集,显示0的 –

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周内没有条目的记录的值。

+0

JOIN是给我麻烦的部分,我需要帮助。此查询返回GROUPed BY周的值,但不返回0值,这是我缺少的部分。谢谢萨加尔。 –

+0

@CraigHowell我知道你只需要做一个日历表,并使整个查询加入它。 –

+1

https://stackoverflow.com/questions/20677472/sql-find-missing-date-ranges看到这个问题来创建日期范围。 – Shuddh