T-SQL SELECT查询(t-sql select query)

2019-10-23 07:56发布

根据下表上

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

Answer 1:

这里有一个简单的方法做你的支点,使用名为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                 


Answer 2:

这是一件更有意义的应用程序比SQL做。 做一个:

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

然后让应用程序透视数据。 通常应用程序可以比SQL可以更有效地枢转的数据。 Espcially当列数每次改变你运行它。



Answer 3:

它看起来像台转动时,我的意思是,列可能应该行。 这种类型的设计是非常人性化的可读性,但不是很可查询。

看看UNPIVOT运算符。 你应该能够用它来获得与您可以过滤对,然后当你做,你可以支点回到这个格式,如果需要行的数据集。

这里有一个文章: http://msdn.microsoft.com/en-us/library/ms177410.aspx

UNPIVOT通过旋转列成行执行几乎枢轴的相反的操作,。



Answer 4:

简短的回答是否定的。 我做了一些测试。 我会给你的代码,因为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 


Answer 5:

您可以生成必要的SQL SELECT语句,然后使用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年一个更好的方法。



文章来源: t-sql select query