01.
if object_id ( N
'dbo.test_table'
,
N
'U'
)
is
not
null
02.
drop
table
dbo.test_table;
03.
go
04.
05.
create
table
dbo.test_table ( id
int
identity
06.
,
a
int
07.
,
b
int
08.
,
c
int
09.
,
d
int
10.
,
e
int
11.
);
12.
go
13.
14.
insert
into
dbo.test_table
15.
select
10, 5, 12, 56, 2
16.
union
all
17.
select
100, 45, 78, 6, 122
18.
union
all
19.
select
150, 50, 127, 596, 22
20.
union
all
21.
select
3410, 55, 0, -45, 90
22.
union
all
23.
select
-10, -5, 0, -56, -2;
20.union
all
21.
select
3410, 55, 0, -45, 90
22.
union
24.
go
max 01.png
А теперь несколько примеров, как найти максимум в каждой строке по всем колонкам.
1. Выражение CASE (любая версия)
01.
select
*
02.
, max_val =
case
when
( a >= b )
and
( a >= c )
and
( a >= d )
and
( a >= e )
03.
then
a
04.
when
( b >= a )
and
( b >= c )
and
( b >= d )
and
( b >= e )
05.
then
b
06.
when
( c >= a )
and
( c >= b )
and
( c >= d )
and
( c >= e )
07.
then
c
08.
when
( d >= a )
and
( d >= b )
and
( d >= c )
and
( d >= e )
09.
then
d
10.
else
e
11.
end
12.
from
dbo.test_table
2. Подзапрос и оператор UNION (любая версия)
01.
select
*
02.
, max_val =
(
select
max
(i)
03.
from
(
select
a
04.
union
all
05.
select
b
06.
union
all
07.
select
c
08.
union
all
09.
select
d
10.
union
all
11.
select
e
12.
)
t(i)
13.
)
14.
from
dbo.test_table
3. Подзапрос и предложение VALUES (SQL Server 2008 и выше)
01.
select
*
02.
, max_val =
(
select
max
(i)
03.
from
(
values
(a)
04.
,(b)
05.
,(c)
06.
,(d)
07.
,(e)
08.
&nbcode>
,(d)
07.
,(e)
)
t(i)
09.
)
10.
from
dbo.test_table
4. Оператор UNPIVOT (SQL Server 2005 и выше)
1.
select
id,
max
(val)
as
max_val
2.
from
(
select
*
3.
from
dbo.test_table t
4.
unpivot
( val
for
col
in
( [a],[b],[c],[d],[e]) ) up
5.
6.
) t
7.
group
by
id
5. Оператор UNPIVOT и ранжирующие функции (SQL Server 2005 и выше)
1.
select
top
1
with
ties id, val
2.
from
dbo.test_table t
3.
unpivot ( val
for
col
in
( [a],[b],[c],[d],[e]) ) up
4.
order
by
row_number() over ( partition
by
id
order
by
val
desc
)
6. Оператор CROSS APPLY (SQL Server 2005 и выше)
01.
select
*
02.
from
dbo.test_table t
03.
cross
apply (
select
top
1 val
04.
from
(
values
(a),(b),(c),(d),(e) ) t (val)
05.
order
by
val
desc
06.
)
ca (max_val)
07.
08.
--Ещё вариант
09.
desc
06.
)
ca (max_val)
07.
08.
--Ещё вариант
10.
select
id, a, b, c, d, e, max_val
11.
from
dbo.test_table t
12.
cross
apply (
select
row_number() over (
order
by
val
desc
) i, val
13.
from
(
values
(a),(b),(c),(d),(e) ) t (val)
14.
)
ca (i, max_val)
15.
where
ca.i = 1
7. Inline-функция и CTE (SQL Server 2005 и выше)
01.
if object_id ( N
'dbo.f_get_max'
,
N
'IF'
)
is
not
null
02.
drop
function
dbo.f_get_max;
03.
go
04.
create
function
dbo.f_get_max (
05.
@a
int
06.
, @b
int
07.
, @c
int
08.
, @d
int
09.
, @e
int
10.
)
returns
table
11.
as
12.
return
13.
with
cte
14.
as
11.
as
12.
return
13.
with
cte
14.
as
(
select
val
from
16.
(
values
(@a),(@b),(@c),(@d),(@e)
17.
) t(val)
18.
)
19.
select
max
(val)
as
max_val
from
cte;
20.
go
21.
22.
select
*
from
dbo.test_table t
23.
cross
apply dbo.f_get_max ( a, b, c, d, e )
24.
go
А теперь посмотрим на производительность этих запросов, чтобы определить, какой из вариантов более предпочтителен. Тест буду проводить также на 5 колонках таблицы с 10 млн. записей.
001.
set
nocount
on
;
002.
go
003.
004.
if object_id ( N
'dbo.test_table'
,
N
'U'
)
is
not
null
005.
drop
table
dbo.test_table;
006.
go
007.
008.
create
table
dbo.test_table ( id
int
identity
primary
key
clustered
009.
,
a
int
010.
,
b
int
011.
,
c
int
012.
,
d
int
013.
,
e
int
014.
);
015.
go
016.
,
e
int
014.
);
015.
go
017.
--Генерим 10 млн строк
018.
with
cte
019.
as
020.
(
021.
select
1 i
022.
union
all
023.
select
i+1
from
cte
where
i < 10000000
024.
)
025.
insert
into
dbo.test_table
026.
select
checksum ( newid() ) % 1000
as
a
027.
, checksum
( newid() ) % 1000
as
b
028.
, checksum
( newid() ) % 1000
as
c
029.
, checksum
( newid() ) % 1000
as
d
030.
, checksum
( newid() ) % 1000
as
e
031.
from
cte
032.
option
( maxrecursion 0 );
033.
034.
declare
@val
int
;
035.
036.
print
'1. Выражение CASE (любая версия)'
;
037.
set
statistics
time
on
;
038.
039.
select
@val =
case
when
( a >= b )
and
( a >= c )
and
( a >= d )
and
( a >= e )
040.
then
a
041.
when
( b >= a )
and
( b >= c )
and
( b >= d )
and
( b >= e )
042.
then
b
043.
when
( c >= a )
and
( c >= b )
and
( c >= d )
and
( c >= e )
044.
then
c
045.
when
( d >= a )
and
( d >= b )
and
( d >= c )
and
( d >= e )
046.
then
d
047.
else
e
048.
end
049.
from
dbo.test_table;
050.
051.
set
statistics
time
off
;
052.
053.
print
'2. Подзапрос и оператор UNION (любая версия)'
;
054.
set
statistics
time
on
;
055.
056.
select
@val = (
select
max
(i)
057.
from
(
select
a
058.
union
all
059.
select
b
060.
union
all
061.
select
c
062.
union
all
063.
select
d
064.
union
all
065.
select
e
066.
)
t(i)
067.
)
068.
from
dbo.test_table;
069.
070.
set
statistics
time
off
;
071.
072.
print
'3. Подзапрос и предложение VALUES (SQL Server 2008 и выше)'
;
073.
set
statistics
time
on
;
074.
075.
select
@val = (
select
max
(i)
076.
from
(
values
(a)
077.
,(b)
078.
,(c)
079.
,(d)
080.
,(e)
081.
)
t(i)
082.
)
083.
from
dbo.test_table;
084.
085.
set
statistics
time
off
;
086.
087.
print
'4. Оператор UNPIVOT (SQL Server 2005 и выше)'
;
088.
set
statistics
time
on
;
089.
090.
select
@val =
max
(val)
091.
from
(
select
*
092.
from
dbo.test_table t
093.
unpivot
( val
for
col
in
( [a],[b],[c],[d],[e]) ) up
094.
095.
) t
096.
group
by
id;
097.
098.
set
statistics
time
off
;
099.
100.
print
'5. Оператор UNPIVOT и ранжирующие функции (SQL Server 2005 и выше)'
;
101.
set
statistics
time
on
;
102.
103.
select
top
1
with
ties @val = val
104.
from
dbo.test_table t
105.
unpivot ( val
for
col
in
( [a],[b],[c],[d],[e]) ) up
top
1
with
ties @val = val
104.
&nbsround-color:#f8f8f8;">106.
order
by
row_number() over ( partition
by
id
order
by
val
desc
);
107.
108.
set
statistics
time
off
;
109.
110.
print
'6. Оператор CROSS APPLY (SQL Server 2005 и выше)'
;
111.
112.
print
'CROSS APPLY 1'
;
113.
set
statistics
time
on
;
114.
select
@val = max_val
115.
from
dbo.test_table t
116.
cross
apply (
select
top
1 val
117.
from
(
values
(a),(b),(c),(d),(e) ) t (val)
118.
order
by
val
desc
119.
)
ca (max_val);
120.
121.
print
'CROSS APPLY 2'
;
122.
select
@val = max_val
123.
from
dbo.test_table t
124.
cross
apply (
select
row_number() over (
122.
order
by
val
desc
) i, val
125.
from
(
values
(a),(b),(c),(d),(e) ) t (val)
126.
)
ca (i, max_val)
127.
where
ca.i = 1;
128.
129.
set
statistics
time
off
;
130.
131.
print
'7. Inline-функция и CTE (SQL Server 2005 и выше)'
;
132.
set
statistics
time
on
;
133.
134.
select
@val = max_val
from
dbo.test_table t
135.
cross
apply dbo.f_get_max ( a, b, c, d, e );
136.
137.
set
statistics
time
off
;
138.
go
Результат ниже:
01.
1. Выражение
CASE
(любая версия)
02.
03.
SQL Server Execution Times:
04.
CPU
time
= 3416 ms, elapsed
time
= 3416 ms.
05.
----------------------------------------------------------------------
06.
07.
2. Подзапрос и оператор
UNION
(любая версия)
08.
09.
SQL Server Execution Times:
10.
CPU
time
= 12777 ms, elapsed
time
= 3848 ms.
11.
----------------------------------------------------------------------
12.
13.
3. Подзапрос и предложение
VALUES
(SQL Server 2008 и выше)
14.
15.
SQL Server Execution Times:
16.
CPU
time
= 13182 ms, elapsed
3. Подзапрос и предложение
VALUES
(SQL Server 2008 и выше)
14.
15.
time
= 3968 ms.
17.
----------------------------------------------------------------------
18.
19.
4. Оператор UNPIVOT (SQL Server 2005
и выше)
20.
21.
SQL Server Execution Times:
22.
CPU
time
= 22246 ms, elapsed
time
= 15966 ms.
23.
----------------------------------------------------------------------
24.
25.
5. Оператор UNPIVOT и ранжирующие функции
(SQL Server 2005 и выше)
26.
27.
SQL Server Execution Times:
28.
CPU
time
= 153957 ms, elapsed
time
= 239071 ms.
29.
----------------------------------------------------------------------
30.
31.
6. Оператор
CROSS
APPLY (SQL Server 2005 и выше)
32.
33.
CROSS
APPLY 1
34.
35.
SQL Server Execution Times:
36.
CPU
time
= 22963 ms, elapsed
time
= 6273 ms.
37.
38.
CROSS
APPLY 2
39.
40.
SQL Server Execution Times:
41.
CPU
time
= 33244 ms, elapsed
time38.
CROSS
APPLY 2
= 9270 ms.
42.
----------------------------------------------------------------------
43.
44.
7. Inline-функция и CTE (SQL Server
2005 и выше)
45.
46.
SQL Server Execution Times:
47.
CPU
time
= 12246 ms, elapsed
time
= 3787 ms.