0

我需要一点帮助。

我有一个表,其中包含用于确定客户评级的参数。

表结构如下:

Column Name       |  Data Type   |  Allow Nulls
-----------------------------------------------
Rating            |  varchar(10) |      N
RedeemedMin       |  int         |      Y  
RedeemedMax       |  int         |      Y
DisposedMin       |  int         |      Y
DisposedMax       |  int         |      Y
RecentDisposedMin |  int         |      Y
RecentDisposedMax |  int         |      Y

以下是我存储在表中的值:

Excellent  |   20     |   99999  |   0      |   0      |   NULL   |   NULL
Good       |   20     |   99999  |   0      |   99999  |   0      |   2
Good       |   1      |   19     |   0      |   2      |   NULL   |   NULL
Good       |   4      |   99999  |   0      |   0      |   NULL   |   NULL
Average    |   20     |   99999  |   3      |   99999  |   NULL   |   NULL
Average    |   1      |   19     |   3      |   99999  |   NULL   |   NULL
Poor       |   0      |   0      |   1      |   99999  |   NULL   |   NULL
Poor       |   NULL   |   NULL   |   0      |   99999  |   4      |   99999
New_       |   0      |   0      |   0      |   0      |   NULL   |   NULL

我需要能够做的是:

在存储过程中,我需要传入 3 个值:

  • RedeemedCnt int
  • DisposedCnt int
  • 最近的DisposedCnt int

根据传入的这些值,我想返回一个评级:

例如,如果我传入:

RedeemedCnt = 35

DisposedCnt = 0

最近的DisposedCnt = 0

那么返回的评级应该是优秀的

如果我通过:

RedeemedCnt = 35

DisposedCnt = 20

最近的DisposedCnt = 2

那么返回的评分应该是Good

如果我通过:

RedeemedCnt = 35

DisposedCnt = 20

最近的DisposedCnt = 0

那么返回的评分应该是Average

上面的例子来源于我们的业务规则,但我试图将其设置为基于上面表值的存储过程,以使其更加灵活。

我已经开始查询,但 WHERE 子句似乎有问题,因为它不返回单个结果:

DECLARE @redeemedCnt int = 35
DECLARE @disposedCnt int = 0
DECLARE @recentDisposedCnt int = 0

SELECT
    Rating
FROM
    CustomerRatingParameters
WHERE       
    (RedeemedMin <= @redeemedCnt AND RedeemedMax >= @redeemedCnt) AND
    (DisposedMin <= @disposedCnt AND DisposedMax >= @disposedCnt) AND
    (RecentDisposedMin <= @recentDisposedCnt AND RecentDisposedMax >= @recentDisposedCnt)

我需要有条件的 WHERE 子句还是整个语句都需要有条件?

请有人可以提供一些帮助。

干杯。


更新

由于这种变化是由于将代码从 C# 代码移动到数据库中而发生的,我认为提供当前的 C# IF... 语句可能很有用:

public CustomerRating GetCustomerRating(int customerID)
{
    CustomerRating cr = CustomerRating.None;

    IList<Item> redeemed;
    IList<Item> disposed;

    int countRedeemed = 0;
    int countDisposed = 0;
    int countRecentlyDisposed = 0;
    DateTime twoYearsAgo = DateTime.Now.AddYears(-2);

    try
    {
        redeemed = GetItems(customerID, "R");
        disposed = GetItems(customerID, "D");

        countRedeemed = redeemed.Count();
        countDisposed = disposed.Count();

        // Select items where disposal date is within the last two years.
        var recentlyDisposed = from p in disposed
                               where p.DisposedDate.HasValue && p.DisposedDate.Value.Date > twoYearsAgo.Date
                               select p;

        countRecentlyDisposed = recentlyDisposed.Count();

        if (countRedeemed >= 20)
        {
            if (countDisposed == 0)
            {
                cr = CustomerRating.Excellent;
            }
            else if (countRecentlyDisposed < 3)
            {
                cr = CustomerRating.Good;
            }
            else if (countDisposed >= 3)
            {
                cr = CustomerRating.Average;
            }
        }
        else if (countRedeemed >= 1 && countRedeemed <= 19)
        {
            if (countDisposed < 3)
            {
                cr = CustomerRating.Good;
            }
            else if (countDisposed >= 3)
            {
                cr = CustomerRating.Average;
            }
        }
        else if (countRedeemed >= 4 && countRedeemed <= 99999)
        {
            if (countDisposed == 0)
            {
                cr = CustomerRating.Good;
            }
        }
        else if (countRedeemed == 0)
        {
            if (countDisposed == 0)
            {
                cr = CustomerRating.New_;
            }
            else if (countDisposed > 0)
            {
                cr = CustomerRating.Poor;
            }
        }

        if (countRecentlyDisposed >= 3)
        {
            cr = CustomerRating.Poor;
        }
    }
    catch (Exception)
    {
        //throw;
    }

    return cr;
}
4

1 回答 1

1

返回多个结果有几个原因:

  1. 您应该避免使用NULLCustomerRatingParameters或检查子句中的NULL值。WHERE
  2. 您应该检查您的值范围是否相交。例如,看看你的配置Poor- 它匹配任何初始值。

在 DB 中配置此类计算的整个想法非常好 - 当条件发生变化时,您无需更改软件。但是您可以更进一步并重新设计您的数据库,即使业务需要更多标准来计算评级,例如 VisitedCnt、RejectedCnt 等。为此,您应该举个例子:

  • 为参数类型添加表格,例如CustomerRatingParameterTypes- Redeemed、Disposed、RecentDisposedCnt 等。
  • 将表修改为CustomerRatingParameters以下结构:ParameterType、Rating、ParameterMin、ParameterMax。

因此,您可以将表变量作为参数传递给包含所有需要的源对 ParameterType/ParameterValue 的存储过程。

更新和更新-2

添加Priority列。表结构变为如下:

Column Name       |  Data Type   |  Allow Nulls
-----------------------------------------------
Priority          |  int         |      N
Rating            |  varchar(10) |      N
RedeemedMin       |  int         |      Y  
RedeemedMax       |  int         |      Y
DisposedMin       |  int         |      Y
DisposedMax       |  int         |      Y
RecentDisposedMin |  int         |      Y
RecentDisposedMax |  int         |      Y

数据改为:

1 |    Excellent  |   20     |   99999  |   0      |   0      |   NULL   |   NULL
2 |    Good       |   20     |   99999  |   0      |   99999  |   0      |   2
3 |    Good       |   1      |   19     |   0      |   2      |   NULL   |   NULL
4 |    Good       |   4      |   99999  |   0      |   0      |   NULL   |   NULL
5 |    Average    |   20     |   99999  |   3      |   99999  |   NULL   |   NULL
6 |    Average    |   1      |   19     |   3      |   99999  |   NULL   |   NULL
7 |    Poor       |   0      |   0      |   1      |   99999  |   NULL   |   NULL
8 |    Poor       |   NULL   |   NULL   |   0      |   99999  |   4      |   99999
9 |    New_       |   0      |   0      |   0      |   0      |   NULL   |   NULL

SELECT陈述:

DECLARE @redeemedCnt int = 35
DECLARE @disposedCnt int = 0
DECLARE @recentDisposedCnt int = 0

SELECT TOP(1)    -- Select only one record
    Rating
FROM
    CustomerRatingParameters
WHERE       
    (RedeemedMin <= @redeemedCnt AND RedeemedMax >= @redeemedCnt) AND
    (DisposedMin <= @disposedCnt AND DisposedMax >= @disposedCnt) AND
    (RecentDisposedMin <= @recentDisposedCnt AND RecentDisposedMax >= @recentDisposedCnt)
ORDER BY Priority ASC    -- Order records with Priority
于 2013-07-18T12:09:35.973 回答