2017-04-16 102 views
1

如果这是重复的(很可能),我很抱歉。我花了很长时间搜索,找不到我的问题的确切答案。禁用GROUP BY列

我已经建立了返回无论是年,月或只是一年分组的行,根据不同的参数SQL函数(在MSSQL):

CREATE FUNCTION get_report (@grouping VARCHAR(30)) 
RETURNS TABLE 
AS 
RETURN 
(
SELECT 
    YEAR(t.my_date) as my_year, 
    CASE when @grouping = 'monthly' THEN MONTH(t.my_date) ELSE null END as my_month, 
    count(t.row_id) as num_rows, 
    round(avg(my_val),4) as avg_my_val 
FROM 
    my_schema.my_info t 
GROUP BY 
    year(t.my_date), 
    CASE when @grouping = 'monthly' THEN month(t.my_date) ELSE null END 
) 

这成功地通过一个月给我一组或这取决于我希望如何报告。

但理想情况下,我想选择让@grouping = 'none'完全消除分组并仅显示项目列表。我试图强制这个查询做得太多,但可能不是。我试过类似GROUP BY 0之类的东西,但是这并没有达到我想要的效果,GROUP BY rand()似乎太凌乱了。

有什么建议吗?

+0

MSSQL,对不起,我要添加该的问题 – Stephen

+0

检查我的答案,请 –

+0

完成,谢谢。 – Stephen

回答

2

试试这个:

use tsql2012 

create table dbo.test18 
(
    year int not null, 
    month int not null, 
    value int 
); 

insert into dbo.test18 
values (2017, 4, 250), (2017, 4, 150), (2017, 4, 660), (2017, 4, 1110), (2017, 3, 1250), (2017, 2, 2540), (2017, 3, 2500) 

declare @a varchar(30) = 'none' 

select * from (
    select grouping_id(year, month, value) as gr_id, year, month, sum(value) as sm 
    from dbo.test18 
    group by grouping sets((year), (month), (year, month), (year, month, value)) 
) t 
where 
    gr_id < case when @a = 'none' then 1 else 999 end 
    and gr_id > case when @a = 'none' then -1 else 0 end 
+0

这个答案看起来给了我想要的东西,所以我接受了它。我的项目计划已经发生了变化,但如果将来使用它,看起来我只需要添加where条件来查找正确的grouping_id。 – Stephen

1

你不能参数化分组 - 同样你不能参数化查询结构(因为它会导致不能被缓存的不同执行计划)。

有三种解决方案:

  1. 使用动态SQL(即建立T-SQL中的SQL字符串,这必须是在一个存储过程,而不是一个UDF)。
  2. 使用无论如何动态生成SQL的ORM(例如Linq-to-Entities或NHibernate等)
  3. 为非分组版本创建第二个UDF。