SQL语句中,能够在group by段落里面使用可能为null的参数,能否不使用SQL拼接解决问题?

shoppo0505 2017-11-30 10:19:00
写了个存储过程,大致结构如下:
sp_Name
(
@param1 int
, @param2 int
, @param3 int
)
AS
BEGIN
SELECT 所需列 FROM Table
WHERE 列1 = @param1 AND 列2 = @param2 AND 列3 = @param3
GROUP BY 列X,列Y
(这里改怎么写?这里如果@param1 IS NOT NULL的话,需要将列1添加进group by 组中,@param2,@param3也是一样)

where条件中好处理,完全没有问题,但是group by中怎么处理?
...全文
750 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
shoppo0505 2017-12-01
  • 打赏
  • 举报
回复
引用 9 楼 yenange 的回复:
[quote=引用 7 楼 shoppo0505 的回复:] [quote=引用 3 楼 yenange 的回复:]
USE tempdb
GO
IF OBJECT_ID('t') IS NOT NULL DROP TABLE t
GO
CREATE TABLE  t(c1 INT,c2 INT,c3 INT)
GO
INSERT INTO t VALUES (1,2,3)
INSERT INTO t VALUES (1,2,4)
INSERT INTO t VALUES (1,3,5)
INSERT INTO t VALUES (2,4,3)
GO
IF EXISTS(SELECT * FROM sys.procedures AS p WHERE p.name='ProcTest')
BEGIN
	DROP PROC ProcTest
END
GO
CREATE PROC dbo.ProcTest
	@p1 INT,
	@p2 INT,
	@p3 INT
AS
BEGIN
	SET NOCOUNT ON;
	DECLARE @sql NVARCHAR(MAX),@sqlWhere NVARCHAR(MAX),@sqlGroup NVARCHAR(MAX)
	SET @sql=''
	SET @sqlWhere=' where 1=1 '
	SET @sqlGroup=''
	IF @p1 IS NOT NULL
	BEGIN
		SET @sql=@sql+',c1'
		SET @sqlWhere=@sqlWhere+ ' and c1=@p1 '
		SET @sqlGroup=CASE WHEN @sqlGroup>'' THEN ' ,c1 ' ELSE ' GROUP BY c1 ' END
	END
	IF @p2 IS NOT NULL
	BEGIN
		SET @sql=@sql+',c2'
		SET @sqlWhere=@sqlWhere+' and c2=@p2 '
		SET @sqlGroup= @sqlGroup+ CASE WHEN @sqlGroup>'' THEN ' ,c2 ' ELSE ' GROUP BY c2 ' END
	END
	IF @p3 IS NOT NULL
	BEGIN
		SET @sql=@sql+',c3'
		SET @sqlWhere=@sqlWhere+' and c3=@p2 '
		SET @sqlGroup=@sqlGroup+ CASE WHEN @sqlGroup>'' THEN ' ,c3 ' ELSE ' GROUP BY c3 ' END
	END
	SET @sql='select '+SUBSTRING(@sql,2,LEN(@sql))+',count(1) as cnt from t '+@sqlWhere+@sqlGroup
	PRINT @sql
	EXEC sp_executesql @sql,N'@p1 int,@p2 int,@p3 int',@p1,@p2,@p3
END
GO
EXEC dbo.ProcTest 1,3,NULL

你的需求这么复杂, 只能用动态SQL 来实现。 如果实在不用也行,那就得把每种组合情况都写下来, 代码都是这个的好多倍了, 不值。
现在也是这么做的,但是问题是,select出来结果还只是第一步,之后还要做好多处理,头有点大。[/quote] 那无所谓呀,用 Select * into #tmp from t 将结果保存到临时表了,后面随便你怎么玩[/quote] 对的,脑子抽抽了,用CTE解决问题了。
吉普赛的歌 2017-12-01
  • 打赏
  • 举报
回复
引用 7 楼 shoppo0505 的回复:
[quote=引用 3 楼 yenange 的回复:]
USE tempdb
GO
IF OBJECT_ID('t') IS NOT NULL DROP TABLE t
GO
CREATE TABLE  t(c1 INT,c2 INT,c3 INT)
GO
INSERT INTO t VALUES (1,2,3)
INSERT INTO t VALUES (1,2,4)
INSERT INTO t VALUES (1,3,5)
INSERT INTO t VALUES (2,4,3)
GO
IF EXISTS(SELECT * FROM sys.procedures AS p WHERE p.name='ProcTest')
BEGIN
	DROP PROC ProcTest
END
GO
CREATE PROC dbo.ProcTest
	@p1 INT,
	@p2 INT,
	@p3 INT
AS
BEGIN
	SET NOCOUNT ON;
	DECLARE @sql NVARCHAR(MAX),@sqlWhere NVARCHAR(MAX),@sqlGroup NVARCHAR(MAX)
	SET @sql=''
	SET @sqlWhere=' where 1=1 '
	SET @sqlGroup=''
	IF @p1 IS NOT NULL
	BEGIN
		SET @sql=@sql+',c1'
		SET @sqlWhere=@sqlWhere+ ' and c1=@p1 '
		SET @sqlGroup=CASE WHEN @sqlGroup>'' THEN ' ,c1 ' ELSE ' GROUP BY c1 ' END
	END
	IF @p2 IS NOT NULL
	BEGIN
		SET @sql=@sql+',c2'
		SET @sqlWhere=@sqlWhere+' and c2=@p2 '
		SET @sqlGroup= @sqlGroup+ CASE WHEN @sqlGroup>'' THEN ' ,c2 ' ELSE ' GROUP BY c2 ' END
	END
	IF @p3 IS NOT NULL
	BEGIN
		SET @sql=@sql+',c3'
		SET @sqlWhere=@sqlWhere+' and c3=@p2 '
		SET @sqlGroup=@sqlGroup+ CASE WHEN @sqlGroup>'' THEN ' ,c3 ' ELSE ' GROUP BY c3 ' END
	END
	SET @sql='select '+SUBSTRING(@sql,2,LEN(@sql))+',count(1) as cnt from t '+@sqlWhere+@sqlGroup
	PRINT @sql
	EXEC sp_executesql @sql,N'@p1 int,@p2 int,@p3 int',@p1,@p2,@p3
END
GO
EXEC dbo.ProcTest 1,3,NULL

你的需求这么复杂, 只能用动态SQL 来实现。 如果实在不用也行,那就得把每种组合情况都写下来, 代码都是这个的好多倍了, 不值。
现在也是这么做的,但是问题是,select出来结果还只是第一步,之后还要做好多处理,头有点大。[/quote] 那无所谓呀,用 Select * into #tmp from t 将结果保存到临时表了,后面随便你怎么玩
shoppo0505 2017-12-01
  • 打赏
  • 举报
回复
引用 6 楼 ayalicer 的回复:
这个语句 是不是不管 3个参数 是什么 结果只有一行? 如果那样group 有什么意义?
因为是做数据统计,假设说@param1为null,那么选取条件中@param1不起作用,但是因为需要选取出来此列信息,并且数据要计算入统计结果,所以需要添加到group by中
shoppo0505 2017-12-01
  • 打赏
  • 举报
回复
引用 3 楼 yenange 的回复:
USE tempdb
GO
IF OBJECT_ID('t') IS NOT NULL DROP TABLE t
GO
CREATE TABLE  t(c1 INT,c2 INT,c3 INT)
GO
INSERT INTO t VALUES (1,2,3)
INSERT INTO t VALUES (1,2,4)
INSERT INTO t VALUES (1,3,5)
INSERT INTO t VALUES (2,4,3)
GO
IF EXISTS(SELECT * FROM sys.procedures AS p WHERE p.name='ProcTest')
BEGIN
	DROP PROC ProcTest
END
GO
CREATE PROC dbo.ProcTest
	@p1 INT,
	@p2 INT,
	@p3 INT
AS
BEGIN
	SET NOCOUNT ON;
	DECLARE @sql NVARCHAR(MAX),@sqlWhere NVARCHAR(MAX),@sqlGroup NVARCHAR(MAX)
	SET @sql=''
	SET @sqlWhere=' where 1=1 '
	SET @sqlGroup=''
	IF @p1 IS NOT NULL
	BEGIN
		SET @sql=@sql+',c1'
		SET @sqlWhere=@sqlWhere+ ' and c1=@p1 '
		SET @sqlGroup=CASE WHEN @sqlGroup>'' THEN ' ,c1 ' ELSE ' GROUP BY c1 ' END
	END
	IF @p2 IS NOT NULL
	BEGIN
		SET @sql=@sql+',c2'
		SET @sqlWhere=@sqlWhere+' and c2=@p2 '
		SET @sqlGroup= @sqlGroup+ CASE WHEN @sqlGroup>'' THEN ' ,c2 ' ELSE ' GROUP BY c2 ' END
	END
	IF @p3 IS NOT NULL
	BEGIN
		SET @sql=@sql+',c3'
		SET @sqlWhere=@sqlWhere+' and c3=@p2 '
		SET @sqlGroup=@sqlGroup+ CASE WHEN @sqlGroup>'' THEN ' ,c3 ' ELSE ' GROUP BY c3 ' END
	END
	SET @sql='select '+SUBSTRING(@sql,2,LEN(@sql))+',count(1) as cnt from t '+@sqlWhere+@sqlGroup
	PRINT @sql
	EXEC sp_executesql @sql,N'@p1 int,@p2 int,@p3 int',@p1,@p2,@p3
END
GO
EXEC dbo.ProcTest 1,3,NULL

你的需求这么复杂, 只能用动态SQL 来实现。 如果实在不用也行,那就得把每种组合情况都写下来, 代码都是这个的好多倍了, 不值。
现在也是这么做的,但是问题是,select出来结果还只是第一步,之后还要做好多处理,头有点大。
  • 打赏
  • 举报
回复
每种组合情况都写下来 那得8种情况了~
nettman 2017-12-01
  • 打赏
  • 举报
回复
学习了
吉普赛的歌 2017-12-01
  • 打赏
  • 举报
回复
USE tempdb
GO
IF OBJECT_ID('t') IS NOT NULL DROP TABLE t
GO
CREATE TABLE  t(c1 INT,c2 INT,c3 INT)
GO
INSERT INTO t VALUES (1,2,3)
INSERT INTO t VALUES (1,2,4)
INSERT INTO t VALUES (1,3,5)
INSERT INTO t VALUES (2,4,3)
GO
IF EXISTS(SELECT * FROM sys.procedures AS p WHERE p.name='ProcTest')
BEGIN
	DROP PROC ProcTest
END
GO
CREATE PROC dbo.ProcTest
	@p1 INT,
	@p2 INT,
	@p3 INT
AS
BEGIN
	SET NOCOUNT ON;
	DECLARE @sql NVARCHAR(MAX),@sqlWhere NVARCHAR(MAX),@sqlGroup NVARCHAR(MAX)
	SET @sql=''
	SET @sqlWhere=' where 1=1 '
	SET @sqlGroup=''
	IF @p1 IS NOT NULL
	BEGIN
		SET @sql=@sql+',c1'
		SET @sqlWhere=@sqlWhere+ ' and c1=@p1 '
		SET @sqlGroup=CASE WHEN @sqlGroup>'' THEN ' ,c1 ' ELSE ' GROUP BY c1 ' END
	END
	IF @p2 IS NOT NULL
	BEGIN
		SET @sql=@sql+',c2'
		SET @sqlWhere=@sqlWhere+' and c2=@p2 '
		SET @sqlGroup= @sqlGroup+ CASE WHEN @sqlGroup>'' THEN ' ,c2 ' ELSE ' GROUP BY c2 ' END
	END
	IF @p3 IS NOT NULL
	BEGIN
		SET @sql=@sql+',c3'
		SET @sqlWhere=@sqlWhere+' and c3=@p2 '
		SET @sqlGroup=@sqlGroup+ CASE WHEN @sqlGroup>'' THEN ' ,c3 ' ELSE ' GROUP BY c3 ' END
	END
	SET @sql='select '+SUBSTRING(@sql,2,LEN(@sql))+',count(1) as cnt from t '+@sqlWhere+@sqlGroup
	PRINT @sql
	EXEC sp_executesql @sql,N'@p1 int,@p2 int,@p3 int',@p1,@p2,@p3
END
GO
EXEC dbo.ProcTest 1,3,NULL

你的需求这么复杂, 只能用动态SQL 来实现。 如果实在不用也行,那就得把每种组合情况都写下来, 代码都是这个的好多倍了, 不值。
zbdzjx 2017-12-01
  • 打赏
  • 举报
回复
没看太懂,猜测:用case when来判断一下。
二月十六 2017-12-01
  • 打赏
  • 举报
回复
如果group by中的列是判断的,那select 的字段应该也是判断的,不用动态判断拼接可能不好做。
  • 打赏
  • 举报
回复
这个语句 是不是不管 3个参数 是什么 结果只有一行? 如果那样group 有什么意义?

22,210

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧