t-sql select query - PullRequest
       29

t-sql select query

1 голос
/ 19 июня 2010

На основе следующей таблицы

Title Jul-10  Aug-10 Sep-10 Oct-10 Nov-10  Dec-10 Jan-11  Feb-11 Mar-11 Apr-11 May-11 Jun-11
--------------------------------------------------------------------------------------------
A      Null    M1     Null    M2     Null   Null   Null    Null   M3     Null   Null   Null
B      Null    M1     Null    Null   Null   Null   M2      Null   Null   Null   Null   Null
C      Null    Null   Null    Null   Null   M1     Null    Null   Null   Null   Null   Null

Как выбрать только столбцы в определенном диапазоне.

For instance if input variables are:
-------------------------------------
@start = 'Oct-10'
@end = 'Apr-11'

Тогда будет вывод:

Title  Oct-10  Nov-10  Dec-10  Jan-11   Feb-11   Mar-11   Apr-11
-----------------------------------------------------------------
A      M2      Null    Null     Null     Null     M3       Null   
B      Null    Null    Null     M2       Null     Null     Null
C      Null    Null    M1       Null     Null     Null     Null

Ответы [ 5 ]

2 голосов
/ 19 июня 2010

Это то, что для приложения имеет больше смысла, чем SQl. Сделайте:

 select field1, field2 from your table between date1 and date2. 

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

1 голос
/ 19 июня 2010

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

Функция fn_MonthRange () - это рекурсивный CTE, который предоставляет таблицу дат с интервалом в месяц между датами начала и окончания, которую вы затем присоединяете OUTER к своим данным. Это заполнит все пропущенные месяцы.

( fn_DateRange () аналогичен, но работает для произвольных временных отрезков, таких как «каждые 15 минут», каждый час, каждые 3 дня и т. Д.)

    create table #testdata
       (
       id          integer,
       Title       varchar(20),
       TheDate     datetime,
       Metadata    varchar(20)
       )
    go


    insert into #testdata values(1,'A','08/01/2010','M1')
    insert into #testdata values(1,'A','10/05/2010','M2')
    insert into #testdata values(1,'A','03/15/2011','M3')
    insert into #testdata values(2,'B','09/20/2010','M1')
    insert into #testdata values(2,'B','01/15/2011','M2')
    insert into #testdata values(3,'C','12/15/2010','M1')
    go

    declare @mySQL       varchar(MAX);
    declare @StartDate   varchar(20);
    declare @EndDate     varchar(20);

    set @StartDate = '08/01/2010';
    set @EndDate   = '03/15/2011';

    set @mySQL = '
    select
       id,
       Title,
       Left(Datename(month, TheDate),3) + ''-'' + right(cast(Year(theDate) as varchar(4)),2) monyr,
       Metadata
    from
   dbo.fn_MonthRange( ''' + @StartDate + ''',''' + @EndDate + ''') dr

   LEFT OUTER JOIN #testdata td
      on (td.TheDate between dr.startdate and dr.enddate )
where
   dr.StartDate between ''' + @StartDate + ''' and ''' + @EndDate + '''';

    exec pivot_query @mySQL, 'Title', 'monyr','max(Metadata)'
    go

    Result:
Title                Aug-10               Dec-10               Feb-11               Jan-11               Mar-11               Nov-10               Oct-10               Sep-10               
-------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- 
A                    M1                   NULL                 NULL                 NULL                 M3                   NULL                 M2                   NULL                 
B                    NULL                 NULL                 NULL                 M2                   NULL                 NULL                 NULL                 M1                   
C                    NULL                 M1                   NULL                 NULL                 NULL                 NULL                 NULL                 NULL                 
None                 NULL                 NULL                 None                 NULL                 NULL                 None                 NULL                 NULL                 
1 голос
/ 19 июня 2010

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

Посмотрите на оператора UNPIVOT. Вы должны быть в состоянии использовать его для получения набора данных со строками, по которым вы можете фильтровать, а затем, когда вы закончите, вы можете вернуться к PIVOT в этот формат, если вам нужно.

Вот статья: http://msdn.microsoft.com/en-us/library/ms177410.aspx

UNPIVOT выполняет почти обратную операцию PIVOT, вращая столбцы в строки.

0 голосов
/ 19 июня 2010

Вы можете сгенерировать необходимый оператор выбора SQL, а затем использовать sp_executesql для выполнения запроса.

Вот пример того, как сгенерировать имена столбцов месяца:

DECLARE  @nextMonth TABLE(
    currentMonth CHAR(3),
    nextMonth CHAR(3)
);

INSERT INTO @nextMonth(currentMonth, nextMonth)
SELECT 'Jan', 'Feb' UNION ALL
SELECT 'Feb', 'Mar' UNION ALL
SELECT 'Mar', 'Apr' UNION ALL
SELECT 'Apr', 'May' UNION ALL
SELECT 'May', 'Jun' UNION ALL
SELECT 'Jun', 'Jul' UNION ALL
SELECT 'Jul', 'Aug' UNION ALL
SELECT 'Aug', 'Sep' UNION ALL
SELECT 'Sep', 'Oct' UNION ALL
SELECT 'Oct', 'Nov' UNION ALL
SELECT 'Nov', 'Dec' UNION ALL
SELECT 'Dec', 'Jan'

DECLARE @start char(6), @end char(6), @current char(6), @columnNames varchar(1000)
SELECT @start = 'Oct-10', @end = 'Apr-11'

SET @current = @start;
WHILE (@current <> @end)
BEGIN
    IF (@columnNames IS NULL)
        SET @columnNames = @current;
    ELSE
        SET @columnNames = @columnNames + ', ' + @current;

    SELECT @current = nextMonth + '-' + LTRIM(STR(case LEFT(@current, 3) WHEN 'Dec' THEN 1+RIGHT(@current, 2) ELSE RIGHT(@current, 2) END))
    FROM @nextMonth
    WHERE currentMonth = left(@current, 3)
END

SELECT @columnNames

Это дает мне:

Oct-10, Nov-10, Dec-10, Jan-11, Feb-11, Mar-11

Увеличение года можно сделать более явно.Я воспользовался преимуществами автоматического приведения.

У меня есть доступ только к SQL Server 2005, так что, возможно, в 2008 году будет намного лучший способ.

0 голосов
/ 19 июня 2010

Короткий ответ - нет.Я сделал некоторое тестирование.Я дам вам код для игры, но из-за того, как NULL обрабатываются с помощью unpivot, вы потеряете непрерывный диапазон месяцев.Они могут быть добавлены обратно с помощью сводки, но для этого потребуется таблица чисел и т. Д. Слишком много для меня, чтобы сделать 5:02!=)

WITH datepivot
     AS (SELECT title,
                Convert(DATETIME, Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(datecol, 'Jan', '01-01'), 'Feb', '02-01'), 'Mar', '03-01'), 'Apr', '04-01'), 'May', '05-01'), 'Jun', '06-01'), 'Jul', '07-01'), 'Aug', '08-01'), 'Sep', '09-01'), 'Oct', '10-01'), 'Nov', '11-01'), 'Dec', '12-01')) datecol,
                datecol                                                                                                                                                                                                                                                                                                                                origdatecol,
                Isnull(code, 0)                                                                                                                                                                                                                                                                                                                        code
         FROM   (SELECT title,
                        [Jul-10],
                        [Aug-10],
                        [Sep-10],
                        [Oct-10],
                        [Nov-10],
                        [Dec-10],
                        [Jan-11],
                        [Feb-11],
                        [Mar-11],
                        [Apr-11],
                        [May-11],
                        [Jun-11]
                 FROM   test) test UNPIVOT (code FOR datecol IN ([Jul-10], [Aug-10], [Sep-10], [Oct-10], [Nov-10], [Dec-10], [Jan-11], [Feb-11], [Mar-11], [Apr-11], [May-11], [Jun-11]))AS dateunpivot)
--SELECT * from datepivot   --uncomment to view unpivoted data
SELECT *
FROM   (SELECT title,
               code,
               origdatecol
        FROM   datepivot
        WHERE  datecol BETWEEN '10-01-2010' AND '04-01-2011') a PIVOT (Max(code) FOR origdatecol IN ([Jul-10], [Aug-10], [Sep-10], [Oct-10], [Nov-10], [Dec-10], [Jan-11], [Feb-11], [Mar-11], [Apr-11], [May-11], [Jun-11])) b 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...