2017-08-01 61 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