РЕГИСТР SQL Server, КОГДА без использования РЕГИСТРА, КОГДА

StackOverflow https://stackoverflow.com/questions/1682437

  •  18-09-2019
  •  | 
  •  

Вопрос

Есть ли способ переписать инструкцию Transact SQL, которая использует структуру CASE WHEN, чтобы сделать то же самое без использования CASE WHEN?

Я использую продукт, который имеет встроенный конструктор запросов и собственный псевдо-SQL.У него есть ограничения на то, что я могу использовать с SQL Server и Oracle.Итак, у меня есть этот столбец, который, когда базовой базой данных является Oracle, использует DECODE (который поддерживается).Однако мне нужно заставить его работать с SQL Server и В СЛУЧАЕ, КОГДА он не поддерживается.

Утверждение, которое я пытаюсь преобразовать, выглядит примерно так

Decode (StatusColumn,  'Value 1',
Decode(Sign(Now()-TargetDateColumn)),1,'Past
Due', 'Outstanding'),  'Value 2',
Decode(Sign(Now()-TargetDateColumn)),1,'Past
Due', 'Outstanding'),  'Value 3',
Decode(Sign(Now()-TargetDateColumn)),1,'Past
Due', 'Outstanding'),  'Value 4')

У меня есть ограниченный набор параметров T-SQL для использования и СЛУЧАЙ, КОГДА это не вариант.У меня есть IsNull и Coalesce, но я не уверен, помогут ли они мне с этим.

Не утруждайте себя вычислением даты, они решаемы.

Я искал СЛУЧАЙ, КОГДА задавались вопросы здесь, но безрезультатно.

Спасибо!

Обновить:

Я понимаю, что мне следовало бы дать более подробную информацию о причине ограничений, поскольку это ресурс разработчика, и предполагается, что это продукт разработки.Это не так.

Я использую корпоративный программный продукт, который имеет встроенный конструктор запросов и собственный псевдо-SQL.У него есть ограничения на то, что я могу использовать с SQL Server и Oracle.По сути, все, что не нарушает синтаксический анализ встроенного механизма запросов, является игрой.Это означает все разрешенные функции и выражения, плюс все абстракции данных (внутренние объекты, соответствующие физической таблице в базе данных, и другие запросы, созданные с помощью продукта), плюс все из Oracle SQL или Transact SQL, которые явно не прерывают синтаксический анализ.

Причина, по которой CASE WHEN у меня не работает, заключается в том, что это нарушает синтаксический анализ псевдо-SQL с помощью механизма запросов.

В конечном счете, я хотел бы попытаться:

  1. Используйте только запрос продукта разработайте SQL, который передает синтаксический анализ ИЛИ
  2. Используйте несколько дополнительных ресурсов из базы данных SQL Server и конструктора запросов, чтобы выполнить это.

Основываясь на нескольких хороших ответах, которые я получил, вот подход, который сработал для меня на данный момент.

Джейсон ДеФонтес предположил, что я мог бы использовать представление базы данных для выполнения правил CASE WHEN, и это подпадает под # 2 выше.У меня это работает, потому что представление достаточно динамично, и мне не нужно его обслуживать (в отличие от подхода richartallent с таблицами истинности, который, я считаю, близок к подходу Джейсона).Предложение Паскаля о создании функции было бы сделано в том же духе, но, вероятно, нарушило бы синтаксический анализ.

Итак, я создал представление базы данных, которое выполняет все преобразования с помощью CASE WHEN, и я добавил его в SQL моего запроса, объединил его с существующим SQL, и все сработало просто отлично.Я понимаю, что, вероятно, добавляю накладные расходы ядру базы данных, поскольку ему придется дважды извлекать один и тот же набор данных (один для представления и один для запроса), но это один из тех случаев, когда это вряд ли является проблемой.

Учитывая, что этот дизайн "использовать представление, чтобы запутать его" работает для меня, мне интересно, какой подход был бы более эффективным:

  • Использование параметра select with в СЛУЧАЕ, КОГДА;
  • Использование CTE (опять же, richardtallent);
  • Использование Union All (HLGEM);
  • Использование подзапросов (MisterZimbu);

Я все равно проверю предложение Арамиса Уайлера, поскольку оно, вероятно, может попасть в пункт 1 выше.

На данный момент ответ Джейсона был принят.Учитывая, что я использовал CASE WHEN в представлении, возможно, название для вопроса в конечном итоге было выбрано неправильно.Я поддержал всех, кто предложил что-то, что помогло в этом процессе.Я не знаю, повлияет ли это на твою репутацию или нет, но я подумал, что это хороший поступок.

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

Это было полезно?

Решение

Можете ли вы переместить логику CASE / WHEN в представление, а затем заставить инструмент запросить представление?

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

У вас есть union all в наличии?Возможно, вы могли бы написать запрос для каждого из условий с условием case в предложении where и объединить их вместе.

Можете ли вы написать пользовательские подзапросы?Вероятно, нет, если у вас даже нет доступа к CASE WHEN, но это, вероятно, тоже сработало бы:

select
    ...,
    coalesce(c1.value, c2.value, c3.value, ..., <default value>)
from MyTable
left join (select <result 1> as value) c1 on <first condition>
left join (select <result 2> as value) c2 on <second condition>
left join (select <result 3> as value) c3 on <third condition>

Напишите функцию, которая выполняет вычисление, используя CASE WHEN.

Это уродливо, и в зависимости от количества имеющихся у вас значений оно может оказаться нежизнеспособным.Но, строго говоря, я думаю, что что-то подобное сработало бы как перевод из приведенного выше сегмента запроса:

выберите 'PastDue' из tablename, где Now() > TargetDateColumn и (StatusColumn = 'Значение 1' или StatusColumn = 'Значение 2' или StatusColumn = 'Значение 3') объединение выбирает "Выдающийся", где сейчас () < TargetDateColumn и (StatusColumn = 'Значение 1' или StatusColumn = 'Значение 2' или StatusColumn = 'Значение 3') объединение выбирает "Значение 4" там, где НЕТ (StatusColumn = "Значение 1" или StatusColumn = "Значение 2" или StatusColumn = "Значение 3")

Я не совсем уверен, что понимаю ваш код, но это должно дать вам представление о другом подходе.

Сначала создайте таблицу:

CREATE TABLE StatusLookup(
   value nvarchar(255),
   datesign shortint,
   result varchar(255));

Теперь заполните его таблицей истинности (по-видимому, здесь много повторяющейся логики, возможно, это должны быть две таблицы истинности с ПЕРЕКРЕСТНЫМ соединением между ними):

INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 1', -1, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 1', 0, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 1', 1, 'Past Due')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 2', -1, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 2', 0, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 2', 1, 'Past Due')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 3', -1, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 3', 0, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 3', 1, 'Past Due')

Наконец, присоединяйтесь и предоставьте ответ по умолчанию:

SELECT mytable.*, COALESCE(statuslookup.result, 'Value 4')
FROM
    mytable LEFT JOIN statuslookup ON
        statuslookup.value = StatusColumn
        AND statuslookup.datesign = Sign(Now()-TargetDateColumn)

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top