根据传递给查询的3个值返回单个值

时间:2013-07-18 11:35:46

标签: sql-server-2008 stored-procedures where-clause

我需要一些帮助。

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

表结构如下:

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
  • RecentDisposedCnt int

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

例如,如果我传入:

  

RedeemedCnt = 35

     

DisposedCnt = 0

     

RecentDisposedCnt = 0

然后返回的评分应为 优秀

如果我传入:

  

RedeemedCnt = 35

     

DisposedCnt = 20

     

RecentDisposedCnt = 2

然后返回的评分应为 Good

如果我传入:

  

RedeemedCnt = 35

     

DisposedCnt = 20

     

RecentDisposedCnt = 0

然后返回的评分应为 平均值

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

我已经开始查询了,但似乎遇到了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;
}

1 个答案:

答案 0 :(得分:1)

您有几个原因可以返回多个结果:

  1. 您应该避免NULL中的CustomerRatingParameters值,或者应该检查NULL条款中的WHERE值。
  2. 您应该检查您的值范围是否相交。例如,看一下Poor的配置 - 它匹配任何初始值。
  3. 在DB中配置这种类型的计算的整个想法非常好 - 当条件发生变化时,您无需更改软件。但是,即使业务需要更多的评级计算标准,例如,您可以进一步重新设计数据库。 VisitedCnt,RejectedCnt等等。为此你应该作为一个例子:

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

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

    UPDATE和UPDATE-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