Как я могу написать этот код без использования переменных

У меня есть следующий код, который проверяет площадь поверхности продукта и выдает число. Однако это очень эффективно. Как я могу написать этот код с использованием Case When, then вместо переменных и if else?

DECLARE @test DECIMAL(10,2) 

SELECT
    @test = ([WIDTH] / 1000) * ([HEIGHT] / 1000)
FROM
    MAIN.SYSADM.[TABLE]
WHERE
    ID = 854037
    AND POS_NR = 1 


IF (@test > 1)
    BEGIN
    (
    SELECT
        TOP(1)
        360 / SUM(CAST([QTY] AS INT))
    FROM
        MAIN.SYSADM.[TABLE]
    WHERE
        ID = 854037
        AND POS_NR = 1 
        AND BOM_PRODUKT NOT IN (52101,52102,52006,52007,52003,52005,52008,53201,53102)
        AND (
            STL_PRODGRP IN (26,27,28,30,33,35,412,413,415,425,426,427)
            OR BOM_PRODUKT = 50002
        )
    GROUP BY
        BOM_NODE
    )
    END

ELSE
    BEGIN
    (
    SELECT
        TOP(1)
        180 / SUM(CAST([QTY] AS INT))
    FROM
        MAIN.SYSADM.[TABLE]
    WHERE
        ID = 854037
        AND POS_NR = 1 
        AND BOM_PRODUKT NOT IN (52101,52102,52006,52007,52003,52005,52008,53201,53102)
        AND (
            STL_PRODGRP IN (26,27,28,30,33,35,412,413,415,425,426,427) 
            OR BOM_PRODUKT = 50002
        )
    GROUP BY
        BOM_NODE
    ) 
    END

Я пробовал это, но top(1) и GROUP by не работают.

SELECT
    (
    SELECT
        TOP(1)
        (
        CASE
            WHEN CAST(([WIDTH] / 1000) * ([HEIGHT] / 1000) AS DECIMAL(10,2)) > 1
            THEN 360 / SUM(CAST([QTY] AS INT))
            ELSE 180 / SUM(CAST([QTY] AS INT))
        END
        )
    )
FROM
    MAIN.SYSADM.[TABLE]
WHERE
    [ID] = 854037
    AND POS_NR = 1 
    AND BOM_PRODUKT NOT IN (52101,52102,52006,52007,52003,52005,52008,53201,53102)
    AND (
        STL_PRODGRP IN (26,27,28,30,33,35,412,413,415,425,426,427)
        OR BOM_PRODUKT = 50002
    )
GROUP BY
    BOM_NODE  

Обратите внимание, что TOP без ORDER BY — верный признак недостатка. Это означает, что механизм данных может возвращать любые произвольные строки, которые он хочет, и строки могут быть разными каждый раз, когда вы запускаете указанный запрос. Если вы используете TOP, вам необходимо убедиться, что запрос имеет детерминированность ORDER BY, чтобы вы получали последовательные и надежные результаты.

Thom A 08.05.2024 17:44

Здесь есть много вещей, которые вызывают у меня вопросы. Почему вы храните Qty как нечто иное, чем int? Вы понимаете целочисленную математику? Вы делаете какие-то странные вещи с делением и приведением десятичных дробей, чтобы определить, больше ли результат целого числа. По сути, ваши типы данных явно разбросаны повсюду, и работать с ними неинтересно.

Sean Lange 08.05.2024 17:50

Возможно, я это упускаю, но разве между вашими двумя запросами нет единственной разницы: дивиденд 180 или 360?

Thom A 08.05.2024 17:59
However, it's very efficient. это хорошо, нет
siggemannen 08.05.2024 18:22

С таким же успехом вы можете использовать width * height > 1000000, если только вы на самом деле каким-то образом не полагаетесь на целочисленное деление, что кажется сомнительным, учитывая приведение к decimal.

shawnt00 08.05.2024 18:29

В каком смысле это не сработало? Я предполагаю, что он начал создавать несколько строк, а не одну.

shawnt00 08.05.2024 18:38

Я понимаю это. Сообщение 8120, уровень 16, состояние 1, строка 3. Столбец «MAIN.SYSADM.TABLE.WIDTH» недопустим в списке выбора, поскольку он не содержится ни в агрегатной функции, ни в предложении GROUP BY. Сообщение 8120, уровень 16, состояние 1, строка 3. Столбец «MAIN.SYSADM.TABLE.STL_HEIGHT» недопустим в списке выбора, поскольку он не содержится ни в агрегатной функции, ни в предложении GROUP BY.

andreas p 08.05.2024 19:11

Мне нужно выяснить, куда поместить Top(1), чтобы он работал с Group by.

andreas p 08.05.2024 19:15

Какова цель расчета всей ширины/высоты? У вас явно есть несколько строк, возвращающихся в результате этого поиска, но выбор переменной маскирует это, молча сохраняя только «последнюю» (которая является произвольной без order by). Вам нужно выяснить, что вам нужно запросить, прежде чем пытаться закрепите его top.

shawnt00 08.05.2024 19:28

У вас синтаксическая ошибка в первом запросе. Он даже не запустится: выберите @test = ([WIDTH]/1000)*(HEIGHT]/1000)

HardCode 08.05.2024 23:07

Пробелы и форматирование имеют значение. Отредактированный код. Добавлен недостающий [ в [HEIGHT].

HardCode 08.05.2024 23:16
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
11
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если ваши данные содержат несколько строк с ID = 854037 и POS_NR = 1, ваш расчет @test фактически вычисляет несколько результатов, последний из которых сохраняется в операторе select @test = .... Если каждая такая строка имеет одинаковые значения WIDTH и HEIGHT, все результаты будут одинаковыми, и не имеет значения, какой из них выбран.

Как только вы поместите это вычисление в предложение WHEN выражения CASE, будет разрешен только один результат. Если все результаты одинаковы, вы можете применить MIN(), MAX() или TOP 1, чтобы ограничить результаты только этим одним значением.

Обновленный запрос будет выглядеть примерно так:

select --top(1)
    BOM_NODE,
    SUM(QTY) as SumQty,
    MAX((WIDTH/1000)*(HEIGHT/1000)) as MaxArea,
    case when (
        select MAX((WIDTH/1000)*(HEIGHT/1000))
        from [TABLE]
        where ID=854037 and POS_NR=1
        ) > 1
    then 360/SUM(CAST(QTY as int))
    else 180/SUM(CAST(QTY as int))
    end as Result 
from [TABLE]
where ID = 854037
and POS_NR = 1 
and BOM_PRODUKT not in (52101,52102,52006,52007,52003,52005,52008,53201,53102)
and (
    STL_PRODGRP in (26,27,28,30,33,35,412,413,415,425,426,427)
    or BOM_PRODUKT = 50002
)
group by BOM_NODE

Я закомментировал top 1 и добавил несколько дополнительных столбцов, чтобы показать некоторые промежуточные результаты. Я также подчистил часть форматирования для улучшения читабельности.

Используя некоторые сгенерированные мной тестовые данные, я получил следующие результаты:

BOM_NODE СуммаКолво Макс. Площадь Результат 1 30 1,5 12 2 5 1,5 72
BOM_NODE СуммаКолво Макс. Площадь Результат 1 30 0,5 6 2 5 0,5 36

См. эту db<>fiddle для демонстрации.

Я также считаю, что у вас возникнут серьезные проблемы с проектированием базы данных, если вы храните атрибуты продукта (например, ширину и высоту) в той же таблице, что и количества. Я предлагаю вам прочитать о «нормализации базы данных» и применить некоторые из этих методов для улучшения вашей модели данных.

Выражения типа CAST(QTY as int) также вызывают подозрения. Вы храните числовые значения в виде текста? Не.

Другие вопросы по теме