Получите уникальное значение из строк, в противном случае примите значение по умолчанию в SQL

#sql #sql-server

Вопрос:

У меня есть список строк продаж, каждая из которых имеет поле валюты. Строка продажи представлена таблицей SALE_LINE, в которой есть поле Валюта для хранения валюты строки продажи.

Я хочу выполнить SQL-запрос, который будет принимать список строк продаж, и если валюта этих строк продаж уникальна для всех, то возьмите эту валюту или установите значение по умолчанию, например доллар.

Например, если у меня есть 3 строки с валютами: EUR, GBP, ZAR, запрос вернет мне ДОЛ. если у меня есть 3 строки с валютами: EUR, EUR, EUR, запрос вернет мне евро.

Мой SQL-запрос выглядит следующим образом:

 DECLARE
    @salesLineIds VARCHAR(MAX),
    @defaultCurrency VARCHAR(10),
    @uniqueCurrency VARCHAR(10)

SET @salesLineIds = '1,2,3';
SET defaultCurrency = 'DOL';

DECLARE
    @ID_LIST table (Id BIGINT)
    
INSERT INTO @ID_LIST SELECT TRY_CAST(value AS BIGINT)
FROM STRING_SPLIT(@salesLineIds, ',')

SELECT @uniqueCurrency =(CASE WHEN 1 = (SELECT COUNT(DISTINCT SL.Currency))
THEN 
    (SELECT DISTINCT SL_CUR.Currency
    from SALE_LINE SL_CUR
    where SL_CUR.Id in (SELECT * FROM @ID_LIST)
    )
ELSE 
    @defaultCurrency
END)
FROM SALE_LINE SL
WHERE SL.Id IN (SELECT * FROM @ID_LIST)
 

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

Приведенный ниже запрос не дает хорошей валюты:

 SELECT @uniqueCurrency =(CASE WHEN 1 = (SELECT COUNT(DISTINCT SL.Currency))
THEN 
    (SELECT DISTINCT SL.Currency
    )
ELSE 
    @defaultCurrency
END)
FROM SALE_LINE SL
WHERE SL.Id IN (SELECT * FROM @ID_LIST)
group by SL.Currency
 

Любая помощь в том, как я могу улучшить работу с SQL, будет оценена по достоинству. Спасибо

Комментарии:

1. «но это может быть не очень хорошая производительность» — это проблема с измеряемой производительностью?

2. @MitchWheat : Я также хочу знать, есть ли лучший способ сделать это.

3. лучше? в каком смысле?

4. Доллар США-это валюта. AUD-это валюта, CAD-это валюта. Но ДОЛ — это не валюта.

Ответ №1:

Вам нужно сгруппировать весь набор, а затем просто проверить наличие различных Currency значений. Если есть только один, то вы можете просто использовать любую агрегацию , например MIN , чтобы получить ее.

 DECLARE
    @salesLineIds VARCHAR(MAX),
    @defaultCurrency VARCHAR(10),
    @uniqueCurrency VARCHAR(10);

SET @salesLineIds = '1,2,3';
SET defaultCurrency = 'DOL';

DECLARE
    @ID_LIST table (Id BIGINT);
    
INSERT INTO @ID_LIST SELECT TRY_CAST(value AS BIGINT)
FROM STRING_SPLIT(@salesLineIds, ',');

SELECT @uniqueCurrency =
  CASE WHEN COUNT(DISTINCT SL.Currency) = 1
    THEN MIN(SL.Currency)
    ELSE @defaultCurrency
  END
FROM SALE_LINE SL
WHERE SL.Id IN (SELECT * FROM @ID_LIST);
 

Я предлагаю CHAR(3) в качестве подходящего типа данных для валюты

Ответ №2:

Если не считать нулей.

 SELECT
    CASE WHEN min(SL.Currency) = max(SL.Currency)
        THEN min(SL.Currency)
        ELSE @defaultCurrency
    END
FROM SALE_LINE SL
WHERE SL.Id IN (SELECT * FROM @ID_LIST);
 

Комментарии:

1. Я не уверен, что вышесказанное будет работать с 3 строками с валютами: EUR, GBP, EUR

2. По сути, это то же самое, что и другой ответ. В вашем примере min не равен max, который проходит по мере необходимости.