【问题标题】:Is there a way to dynamically produce SQL Columns in a select query?有没有办法在选择查询中动态生成 SQL 列?
【发布时间】:2016-11-10 23:07:57
【问题描述】:

我当前的 sql 查询需要过去 6 个月并选择销售额,就像这样

  SUM(CASE WHEN ci.InvoiceDate >= '20160501' AND ci.InvoiceDate <= '20160531' THEN cid.QuantityOrdered ELSE 0 END) AS 'May',
  SUM(CASE WHEN ci.InvoiceDate >= '20160601' AND ci.InvoiceDate <= '20160630' THEN cid.QuantityOrdered ELSE 0 END) AS 'June',
  SUM(CASE WHEN ci.InvoiceDate >= '20160701' AND ci.InvoiceDate <= '20160731' THEN cid.QuantityOrdered ELSE 0 END) AS 'July',
  SUM(CASE WHEN ci.InvoiceDate >= '20160801' AND ci.InvoiceDate <= '20160831' THEN cid.QuantityOrdered ELSE 0 END) AS 'August',
  SUM(CASE WHEN ci.InvoiceDate >= '20160901' AND ci.InvoiceDate <= '20160930' THEN cid.QuantityOrdered ELSE 0 END) AS 'September',
  SUM(CASE WHEN ci.InvoiceDate >= '20161001' AND ci.InvoiceDate <= '20161030' THEN cid.QuantityOrdered ELSE 0 END) AS 'October',

但是,当我在 12 月运行此报告时,因为我在月份名称中进行了硬编码,所以我不会得到 11 月的销售数据。

理想情况下,我想要某种形式的代码,可以动态生成最近 6 个月的选择查询。

这甚至可能吗?有没有人可以指点我了解更多关于动态 SQL 的文档?

谢谢大家!

【问题讨论】:

  • 您需要这些作为列吗?还是行会起作用?
  • 不,肯定需要它们作为列
  • 您想要一个dynamic pivot,这在 SQL Server 中是可行的,但可能会很混乱。如果您可以在客户端工具(报告、表单、网页等)中执行此操作,则用于动态数据透视的 UI 工具通常更简洁、更容易。
  • SQL Server 的版本

标签: sql sql-server sql-server-2008-r2


【解决方案1】:

获取最近 6 个月的名称并使用数据透视构建动态查询:

declare @months nvarchar(max) = ''

;with cte as
(select DATENAME(month, dateadd(MONTH, 0, getdate())) mn, 0 v
union all
select DATENAME(month, dateadd(MONTH, v - 1, getdate())) mn, v - 1
from cte
where v > -5
)
select @months = @months + '[' + mn + '], '
from cte

set @months = SUBSTRING(@months, 1, LEN(@months) - 1)

declare @q nvarchar(max)

set @q = '
select *
from
(
select QuantityOrdered qo
, DATENAME(month, InvoiceDate) mn
from invoicetable
) as s
pivot
(sum(qo) for mn in (' + @months + ')
) p'

exec(@q)

【讨论】:

    【解决方案2】:

    也许这会让你开始

    Declare @Date Date  = '2016-10-01'
    Declare @Months int = 6
    
    Declare @SQL varchar(max)=''
    ;with cte0(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N))
        , cteD(D) As (Select DateAdd(MM,1-Row_Number() over (Order By (Select NULL)),@Date) From cte0 N1, cte0 N2) 
        , cteDate as (Select Top (@Months) DateR1=D,DateR2=DateAdd(DD,-1,DateAdd(MM,1,D)),Title=DateName(MM,D) From cteD)
    Select @SQL=@SQL+','+QuoteName(Title)+'=sum(case when ci.InvoiceDate Between '''+CONVERT(char(10), DateR1,126) +''' and '''+CONVERT(char(10), DateR2,126)+''' Then cid.QuantityOrdered Else 0 End))'+char(13) 
     From  (Select Top (@Months) * From cteDate Order by DateR1) A
    
    Select @SQL = 'Select '+Stuff(@SQL,1,1,'')+' From YourTable '
    Exec(@SQL)
    

    生成以下 SQL

    Select [May]=sum(case when ci.InvoiceDate Between '2016-05-01' and '2016-05-31' Then cid.QuantityOrdered Else 0 End))
    ,[June]=sum(case when ci.InvoiceDate Between '2016-06-01' and '2016-06-30' Then cid.QuantityOrdered Else 0 End))
    ,[July]=sum(case when ci.InvoiceDate Between '2016-07-01' and '2016-07-31' Then cid.QuantityOrdered Else 0 End))
    ,[August]=sum(case when ci.InvoiceDate Between '2016-08-01' and '2016-08-31' Then cid.QuantityOrdered Else 0 End))
    ,[September]=sum(case when ci.InvoiceDate Between '2016-09-01' and '2016-09-30' Then cid.QuantityOrdered Else 0 End))
    ,[October]=sum(case when ci.InvoiceDate Between '2016-10-01' and '2016-10-31' Then cid.QuantityOrdered Else 0 End))
     From YourTable 
    

    【讨论】:

    • EOMONTHFormat 未被识别为函数?
    • @BrendanGooden 2008 年更新
    • @BrendanGooden 也删除了 Format()
    猜你喜欢
    • 1970-01-01
    • 2017-11-06
    • 2015-06-11
    • 2012-01-17
    • 1970-01-01
    • 2019-03-08
    • 1970-01-01
    • 2011-10-01
    • 1970-01-01
    相关资源
    最近更新 更多