0

背景/目的: 会社のデータベースから値を取得するための SQL を含む Coldfusion ドキュメントを作成しています。私たちのチームの営業担当者ごとの変換率 (販売されたライセンス / 登録) を見つけています。RegionalDirectorID各担当者には、追跡に役立つようにユーザーに関連付けられた ID ( ) があります。

質問/問題:問題は、CEO、ヘッド開発者など、あちこちでライセンスを販売する他の従業員がいるということです。8 人の営業担当者がいUserTypeます。別のクエリを使用してそれらの UserTypes を選択し、差別化しています。私たちのデータが混同されないように、他の人からもそれらを選択します。

getUsers以下に示すように、クエリをループ処理するために cfloop を使用しています。これは、ライン(Users.RegionalDirectorID = #getUsers.UserID#)が営業担当者のすべての ID を出力できるようにするためです。 cfloop が入力されていない場合、1 人の営業担当者を示す 1 つの行しか表示されません。cfloop がある場合は、最後の営業担当者を取得します。

コード:

<cfset myQuery = QueryNew("ID, ConversionRate")> 

<cfquery name="getUsers" datasource="#dsn#">
    Select UserID FROM USERS WHERE 
    UserTypeID = 8
    AND ISACTIVE = 1
</cfquery> 

<cfquery name="getREGRD" datasource="#dsn#">
 Select COUNT(DISTINCT(Users.UserID))  AS TOTALREG, RegionalDirectorID
 FROM Users
 WHERE UserTypeID = 3
<!---   <cfloop query="getUsers">
    AND (Users.RegionalDirectorID = #getUsers.UserID#)
    </cfloop>--->
AND (PARENTID IS NULL OR PARENTID = 0)
        <cfif len(selectMonth)>
            AND MONTH(Users.DateStamp) = #selectMonth#
        <cfelse>
            AND MONTH(Users.DateStamp) = #MONTH(NOW())#
        </cfif>
        GROUP BY Users.RegionalDirectorID
</cfquery> 

<cfquery name="getREGRDSold" datasource="#dsn#">
    Select COUNT(DISTINCT(UserTractLicense.UserID))  AS TOTALSOLD, Users.RegionalDirectorID
    FROM  Users, UserTractLicense 
    WHERE Users.UserID = UserTractLicense.UserID 
    AND   Users.UserTypeID = 3 AND
    (PARENTID IS NULL OR PARENTID = 0)
    <cfif len(selectMonth)>
            AND MONTH(Users.DateStamp) = #selectMonth#
    <cfelse>
            AND MONTH(Users.DateStamp) = #MONTH(NOW())#
    </cfif>
    GROUP BY Users.RegionalDirectorID
</cfquery> 

<!---<cfset newRow = QueryAddRow(myQuery, #getREGRD.RecordCount#)>
    <cfloop query="getREGRD">
        <cfset QuerySetCell(myQuery, "ID",  #getREGRD.RegionalDirectorID#, getREGRD.currentRow) />
    </cfloop>   
    <cfloop query="getREGRDSold">
        <cfset QuerySetCell(myQuery, "ConversionRate", #getREGRDSold.TOTALSOLD#/#getREGRD.TOTALREG#, getREGRDSold.currentRow) /> 
    </cfloop>
--->

<!---<cfdump var="#myQuery#">--->
<cfdump var="#getREGRD#">
<cfdump var="#getREGRDSold#">

<cfoutput query="getREGRDSold">
    #getREGRDSold.RegionalDirectorID#
</cfoutput>

cfloop により、newQuery が以下のエラーを発生させていました。そのため、一部がコメント アウトされています。

QueryAddRow 関数の評価中にエラーが発生しました: QueryAddRow 関数のパラメータ > 2、0 は正の整数でなければなりません。
エラーは 70 行目で発生しました。

結果のデータには、クエリの結果から削除したい NULL セルなど、8 の UserTypeID を持たない RegionalDirectorID が含まれています。

サンプル結果

4

1 に答える 1

0

余分なループやクエリではなく、単一の JOIN だけが必要なようです。

Usersテーブルに顧客と営業担当者の両方が格納されている場合は、自己結合が必要になります。つまり、エイリアスUsersを使用して、テーブルをそれ自体に結合します。次に、適切なユーザー タイプでそれぞれをフィルター処理します。このようなもの:

SELECT  cust.RegionalDirectorID
        , COUNT(DISTINCT(lic.UserID))  AS TOTALSOLD
FROM    Users cust
           INNER JOIN Users sales ON sales.UserID = cust.RegionalDirectorID
           INNER JOIN UserTractLicense lic ON lic.UserID = cust.UserID
<!--- customers --->
WHERE   cust.UserTypeID = 3 
<!--- sales reps --->
AND     sales.UserTypeID = 8
... etcetera 
GROUP BY cust.RegionalDirectorID

その他のコメント:

  1. 必ずしも技術的に必要なわけではありませんが、クエリに複数のテーブルが含まれる場合は常に、すべての列名を完全修飾することをお勧めします。

  2. 同じように、すべての変数にスコープを設定してください。たとえば、単に の代わりにFORM.selectMonthorを使用します。URL.selectMonthselectMonth

  3. cfqueryparamすべての可変クエリ パラメータで常に使用します。最も重要な理由は、SQL インジェクションからデータベースを保護することです。また、複数回実行されるクエリのパフォーマンスを向上させるのにも役立ちます。

MONTH(Users.DateStamp) = #selectMonth#

  1. クエリが月番号のみをフィルターしていることに気付きました (月年ではありません)。したがって、selectedMonth = 8 の場合、クエリは「8 月」の月の結果を返します。それはあなたの意図でしたか?そうでない場合は、明らかに年フィルターも追加する必要があります。ただし、通常、インデックス付きの列で関数を使用すると、データベースはインデックスを利用できなくなります。したがって、よりインデックスに適したこのパラダイムの使用を検討できます。

     WHERE  TheDateColumn >= TheStartDateAtMidnight         
     AND    TheDateColumn < TheDayAfterEndDateAtMidnight   
    
于 2016-08-12T16:26:16.253 に答える