2

わかりました、ネストされた SQL ステートメントを使用しています。

営業担当者が書いた最新の 120 件の提案を照会したいと考えています。ネストされたクエリを使用して、システムから最後の 120 件の提案を取得し、ステータスなどに基づいてそれらをフィルター処理しています...

私が抱えている問題は、各セールスマンの提案数をどのように取得するかです。

SQL は明らかに間違っていますが、ここで行き詰まっています。

SELECT 
   CASE userId 
    WHEN '4' THEN 'AT'
    WHEN '3' THEN 'EO'
    WHEN '11' THEN 'CT'
    WHEN '13' THEN 'MH'
    ELSE userId
END AS Salesman,
SUM(contractAmt) as 'Contract Total',
AVG(DATEDIFF(contractDate, proposalDate)) AS averageDays,
SUM(proposalAmt) as pTot,
Count(*) as Contracts,
Count(A.proposalAmt) as Proposals,
(SUM(contractAmt) / SUM(proposalAmt)) AS 'Hit Rate $s',
(Count(*) / Count(A.proposalAmt)) AS 'Hit Rate #s'
FROM
( /* Get the last 120 proposals not in Lead or Proposal status*/
SELECT contractAmt, proposalAmt, contractDate, status, userId, 
    CASE WHEN proposalDate = '0000-00-00'   
        THEN CAST(contractDate as Date)
        else CAST(proposalDate as Date)
    END as proposalDate
FROM project
WHERE (status != 'proposal' and status != 'lead')
/*GROUP BY id*/
ORDER BY contractDate DESC
LIMIT 0, 120) A
WHERE status = 'contract' or status = 'complete'
GROUP BY userId

「Count(A.proposalAmt) as Proposals」と入力すると、フィルター処理されたレコード数がわかります。(契約および完了した注文のみ)

ネストされたビット内で、クエリは 100 個の個別レコードを含む 1 行カウントを返したくありません。userId でグループ化すると、ユーザーごとに提案の数を取得できますが、後でフィルタリングするための個々のレコードがありません。

これを回避するために私が考えることができるいくつかの方法がありますが、それらはすべて最悪です. 別のクエリを実行することもできますが、それは洗練されておらず、私の出力ではうまく機能しません。

データベースはMySqlです。

正しく説明していない場合のワークフロー:

For each user ID
Get the last 100 proposals
Count # of proposals by salesman
Total proposal $ amount by salesman
Count # of contract or complete proposals
Total $ amount of contract and complete jobs
# proposals / # contracts = Hit Rate #'s
$ proposals / $ contracts = Hit Rate $'s
AVERAGE(contract date - proposal date) = Average # days in process

出力は次のようになります。

   Salesman  Avg Days  ProposalTot  ContractTot  HR $'s  Prop #  Con #  HR#'s
   --------------------------------------------------------------------------------------
   EO       |   29.27 |  $30,000  |    $15,000  |  50%  |   30  |   15 | 50%

編集:スキーマを追加

Table project
=============
id, userId, clientId, contactId, projectName, status, description, creationDate, shipDate, estimateAmt, leadAmt, reestimateAmt, proposalAmt, contractAmt, completeAmt, type, subType, estDate, reestDate, proposalDate, contractDate, completeDate, lostDate, onHoldDate, estShip, reestShip, proposalShip, contractShip, completeShip, casperLink, statusChangeTS
-------------
id               int(11) PK
userId           int(11)
clientId         int(11)
contactId        int(11)
projectName      varchar(255)
status           enum('lead','proposal','contract','complete','onHold','lost')
description      text
creationDate     date
shipDate         date
estimateAmt      int(11)
leadAmt          int(11)
reestimateAmt    int(11)
proposalAmt      int(11)
contractAmt      int(11)
completeAmt      int(11)
type             varchar(100)
subType          varchar(100)
estDate          date
reestDate        date
proposalDate     date
contractDate     date
completeDate     date
lostDate         date
onHoldDate       date
estShip          date
reestShip        date
proposalShip     date
contractShip     date
completeShip     date
casperLink       varchar(20)
statusChangeTS   date
4

1 に答える 1

1

これを試して:

SELECT 
    Count(*) as 'Total Proposals',
    SUM(CASE WHEN status = 'complete' or status = 'contract' THEN 1 ELSE 0 END) as 'Total Contracts',
    CASE userId 
        WHEN '4' THEN 'AT'
        WHEN '3' THEN 'EO'
        WHEN '11' THEN 'CT'
        WHEN '13' THEN 'MH'
        ELSE userId
    END AS Salesman,
    SUM(CASE WHEN status = 'complete' or status = 'contract' THEN contractAmt ELSE 0 END) as 'Contract Total',
    AVG(DATEDIFF(contractDate, proposalDate)) AS averageDays,
    SUM(proposalAmt) as pTot,
    (SUM(CASE WHEN status = 'complete' or status = 'contract' THEN contractAmt ELSE 0 END) / SUM(proposalAmt)) AS 'Hit Rate $s',
    (SUM(CASE WHEN status = 'complete' or status = 'contract' THEN 1 ELSE 0 END) / Count(*)) AS 'Hit Rate #s'
FROM
    (/* This inner loop only selects the top 100 records */
    select * FROM project
    WHERE (status != 'proposal' and status != 'lead') and userId = '13'
    order by contractDate DESC
    LIMIT 0, 30) A
GROUP BY userId 

思いついた答えは、WHERE 句を使用してフィルタリングするのではなく、CASE 句を使用してコントラクトを持つレコードをフィルタリングすることでした。契約合計が必要な場合はいつでもこれを行う必要があり、契約金額を自分のステータスを持つものだけにフィルターする必要があります。(DBがすでにそれを処理していない限り。)

総提案 | 総契約数 | セールスマン | 契約合計 | 平均日数 | pTot | ヒット率 $s | ヒット率 #s
30 15MH 160496 46.8 324122 0.4952 0.5
于 2012-06-07T20:58:29.567 に答える