TSQL Max в диапазоне - PullRequest
       0

TSQL Max в диапазоне

1 голос
/ 01 марта 2011

У меня был интересный разговор с некоторыми коллегами о том, как решить следующую проблему.Предположим, у меня есть таблица со следующими столбцами:

foo_1,foo_2, foo_3, field_etc,
Score1, Score2, Score3, Score4, Score5,
MoreFields, MoreScores, EvenMoreScores

Мне нужно создать запрос, который возвращает следующее:

foo_1, foo_2, foo_3, field_etc, MaxScore

Где MaxScore - максимальное значение между Score1, Score2,Score3, Score4, Score5

То, что у нас есть, выглядит примерно так:

SELECT
  foo_1, foo_2, foo_3, field_etc,
  (
    SELECT MAX(foo) as Something
    FROM
    (
      SELECT SomeTable.Score1 AS foo
      UNION ALL
      SELECT     SomeTable.Score2
      UNION ALL
      SELECT     SomeTable.Score3
      UNION ALL
      SELECT     SomeTable.Score4
      UNION ALL
      SELECT     SomeTable.Score5
    ) AS x
  ) AS MaxScore
FROM
  SomeTable

Я чувствую, что должен быть более чистый способ сделать это, но мы не нашли его.Мы избегаем очевидного решения UDF по соображениям производительности.

Было бы замечательно, если бы в tsql была какая-то функция диапазона, поэтому я мог бы сделать:

SELECT
  foo_1, foo_2, foo_3, field_etc, MAX(Score1, Score2, Score3, Score4, Score5) as MaxScore
FROM
  SomeTable

В идеале базовая таблица была бынормализуется, и это не будет проблемой, но у меня нет возможности изменить это здесь.

Ответы [ 4 ]

3 голосов
/ 01 марта 2011

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

2 голосов
/ 01 марта 2011

В MSSQL нет встроенной функции (другие делают, например, Oracle имеет Greatest), но вы можете использовать функцию, которая делает то, что вы хотите:
Есть ли в SQL Server функция Max, которая принимает два значения, такие как Math.Max ​​в .NET?

Вам нужна только определенная пользователем функция, которая принимает два параметра и возвращает максимум, позволяет вызывать ее BIGGEST, вы можете сделать это так:

SELECT
  foo_1, foo_2, foo_3, field_etc, 
  BIGGEST(BIGGEST(BIGGEST(BIGGEST(Score1, Score2), Score3), Score4), Score5) as MaxScore
FROM SomeTable
0 голосов
/ 01 марта 2011

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

;with cte1 as
(
  select
    foo_1, foo_2, foo_3, field_etc,
    case when Score1 > Score2 then Score1 else Score2 end as Score12,
    case when Score3 > Score4 then Score3 else Score4 end as Score34,
    Score5
  from SomeTable
),
cte2 as
(
  select
    foo_1, foo_2, foo_3, field_etc,
    case when Score12 > Score34 then Score12 else Score34 end as Score1234,
    Score5
  from cte1
),
cte3 as
(
  select
    foo_1, foo_2, foo_3, field_etc,
    case when Score5 > Score1234 then Score5 else Score1234 end as MaxScore
  from cte2
)
select *
from cte3
0 голосов
/ 01 марта 2011

Я использую это:

CREATE FUNCTION [GreaterOf2INTs]
  (@a int, @b int)
    RETURNS INT
AS
BEGIN
  DECLARE @greater INT

 IF @a > @b SELECT @greater = @a
 ELSE SELECT @greater = @b

 RETURN @greater
END

Вы можете использовать его несколько раз. Уродливо, но это работает. Это быстрее, чем UNIONs.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...