рубрики: SQL | Дата: 30 июля, 2016
Рассмотрим следующую ситуацию. Допустим у нас есть таблица с несколькими однотипными полями.
И нам надо для каждой записи этой таблицы получить минимальное или максимальное значение из
этих нескольких полей.
Ну и чтобы было веселее добавим условие, что пустые значения надо отбрасывать.
Для примера возьмем таблицу с 4-я полями. В первом поле будет уникальный
идентификатор какого-нибудь документа, а в трех других даты:
Docs | DateBeg | DateEnd | DateChange |
---|---|---|---|
Doc_1 | 2016-02-29 00:00:00 | 2018-03-01 00:00:00 | 2017-05-15 00:00:00 |
Doc_2 | 2017-11-21 00:00:00 | 2016-06-18 00:00:00 | 1753-01-01 00:00:00 |
Для начала создадим нашу тестовую таблицу:
/*Создаем тестовую таблицу*/
Create Table #DocDate (Docs VarChar(10), DateBeg DateTime, DateEnd DateTime, DateChange DateTime)
Insert #DocDate
Select
'Doc_1' AS Docs,
'20160229' AS DateBeg,
'20180301' AS DateEnd,
'20170515' AS DateChange
Union All
Select
'Doc_2' AS Docs,
'20171121' AS DateBeg,
'20160618' AS DateEnd,
'17530101' AS DateChange
Допустим, что нам надо для каждой записи выбрать из трех дат минимальную.
А теперь подумаем как лучше реализовать поставленную задачу.
Первое, что приходит на ум – это использовать конструкцию CASE.
Но даже просто для 3-х полей получается достаточно большой и запутанный кусок кода.
А если еще учесть, что надо исключить пустые значения, то и вовсе беда.
Поэтому для поля где нужна минимальная дата создадим вложенный запрос с использованием
агрегатной функции MIN(). В итоге получаем вот такой достаточно простой код:
/*Создаем тестовую таблицу*/
Create Table #DocDate (Docs VarChar(10), DateBeg DateTime, DateEnd DateTime, DateChange DateTime)
Insert #DocDate
Select
'Doc_1' AS Docs,
'20160229' AS DateBeg,
'20180301' AS DateEnd,
'20170515' AS DateChange
Union All
Select
'Doc_2' AS Docs,
'20171121' AS DateBeg,
'20160618' AS DateEnd,
'17530101' AS DateChange
/*Выборка из тестовой таблицы*/
Select
DocDate.*,
(
Select
MIN(Dates)
From
(Select DateBeg AS Dates Where DateBeg <> '17530101'
Union All
Select DateEnd Where DateEnd <> '17530101'
Union All
Select DateChange Where DateChange <> '17530101') DMin
) AS DateMin
From #DocDate AS DocDate
Drop Table #DocDate
Выполняем код и получаем вот такой результат:
Docs | DateBeg | DateEnd | DateChange | DateMin |
---|---|---|---|---|
Doc_1 | 2016-02-29 00:00:00 | 2018-03-01 00:00:00 | 2017-05-15 00:00:00 | 2016-02-29 00:00:00 |
Doc_2 | 2017-11-21 00:00:00 | 2016-06-18 00:00:00 | 1753-01-01 00:00:00 | 2016-06-18 00:00:00 |
Понятно, что использовать это можно не только для полей с датами, но и для других типов тоже.
Добавить комментарий