SQL Серверная хранимая процедура выполняется правильно только при первом запуске - PullRequest
0 голосов
/ 17 апреля 2020

Я написал это SQL Серверная хранимая процедура, которая вставляет записи в другую таблицу на основе частоты заказов клиентов в другой таблице. Каждому клиенту присваивается ранг в зависимости от частоты его заказа. Когда я создаю процедуру и выполняю ее в первый раз, она работает нормально и вставляет правильные записи в таблицу. Но когда я очищаю таблицу и пытаюсь выполнить процедуру снова, записи не добавляются. Я должен удалить процедуру, перезапустить SSMS и снова создать процедуру, чтобы она снова работала правильно.

Вот процедура:

create procedure TopKCustomer (@CustRank decimal(11,0))
as
    declare CustCursor cursor local for
        select o.CustomerID,c.CustomerName,c.CustomerPostalCode,
            count(o.CustomerID) as 'Order Frequency'
        from (Customer_T c join Order_T o on c.CustomerID=o.CustomerID) 
        group by o.CustomerID,c.CustomerName,c.CustomerPostalCode
        order by [Order Frequency] desc;

    declare @PrevOrderFreq float;
    declare @CurrOrderFreq float;
    declare @CurrRank decimal(11,0);
    declare @CurrCustID decimal(11,0);
    declare @CurrCustName varchar(25);
    declare @CurrCustPostCode varchar(10);

begin
    set @PrevOrderFreq = 0;
    set @CurrOrderFreq = 0;
    set @CurrRank = 0;
    set @CurrCustID = 0;
    set @CurrCustName = '';
    set @CurrCustPostCode = '';

    open CustCursor;

    while @@FETCH_STATUS = 0
    begin
        fetch next from CustCursor into @CurrCustID, @CurrCustName, @CurrCustPostCode, @CurrOrderFreq;

        if @CurrOrderFreq <> @PrevOrderFreq
        begin
            set @CurrRank = (@CurrRank + 1);

            if @CurrRank > @CustRank
            begin
                break;
            end
        end

        insert into TopKCustomer_T
        values (@CurrCustID, @CurrCustName, @CurrCustPostCode, @CurrRank, getdate());

        set @PrevOrderFreq = @CurrOrderFreq;
    end

    close CustCursor;
    deallocate CustCursor;
end

Вот таблицы, с которыми я работаю с:

  • Customer_T (CustomerID, CustomerName, CustomerAddress, CustomerCity, CustomerState, CustomerPostalCode)
  • Order_T (OrderID, CustomerID, OrderDate)
  • TopKCustomer (CustomerID, CustomerName , CustomerPostalCode, CRank, RankGenerateDate)

Ответы [ 2 ]

1 голос
/ 17 апреля 2020

Нет примеров данных или структуры таблицы, поэтому я не знаю, как выглядят ваши данные. Ниже то, что я думаю, вы хотите. Внутренний запрос подсчитывает заказ на одного клиента. Внешний запрос ранжирует их.

SELECT *
    , DENSE_RANK() OVER(PARTITION BY CustomerID ORDER BY OrderFrequency) AS Rnk
FROM (
    SELECT *
        , COUNT(*) OVER (PARTITION BY o.CustomerID) AS OrderFrequency
    FROM Customer_T c 
    JOIN Order_T o ON c.CustomerID = o.CustomerID
) a
1 голос
/ 17 апреля 2020

Я думаю, что проблема в

while @@FETCH_STATUS = 0

Это будет результатом предыдущего извлечения (другими словами извлечения из предыдущего выполнения вашей хранимой процедуры, а не того, что вы хотите).

Обычный способ написания циклов курсора:

while 1 =1 
begin
  fetch next from c into ...
  if @@fetch_status != 0 break 
  ...
 end
...