读书人

sql语句精简有关问题

发布时间: 2012-12-17 09:31:40 作者: rapoo

sql语句精简问题,在线等

SELECT (SELECT sum(nqhje) FROM t_qhb WHERE 
CONVERT(datetime,srq,112)BETWEEN dateadd(dd,-15,@jk) AND @jk)
/
(SELECT sum(nchje) FROM t_chb WHERE
CONVERT(datetime,srq,112)BETWEEN dateadd(dd,-15,@jk) AND @jk) AS 节前15天缺货率
,
(SELECT sum(nqhje) FROM t_qhb WHERE
CONVERT(datetime,srq,112)BETWEEN @jj AND dateadd(dd,15,@jj))
/
(SELECT sum(nchje) FROM t_chb WHERE
CONVERT(datetime,srq,112)BETWEEN @jj AND dateadd(dd,15,@jj)) AS 节后15天缺货率
,
(SELECT sum(nqhje) FROM t_qhb WHERE
CONVERT(datetime,srq,112)BETWEEN dateadd(dd,-15,@jk) AND dateadd(dd,15,@jj))
/
(SELECT sum(nchje) FROM t_chb WHERE
CONVERT(datetime,srq,112)BETWEEN dateadd(dd,-15,@jk) AND dateadd(dd,15,@jj)) AS 前后30天缺货率

t_qhb 缺货表 t _chb 出货表
这段sql好长,条件都重复写了。
有什么办法能精简下语句吗?
[最优解释]
DECLARE @qk  datetime,@jk datetime 
,@qj datetime,@jj datetime
,@str_jk VARCHAR(10),@str_jj VARCHAR(10)

SET @qk='2011-06-21'
SET @jk='2012-06-21'
SET @qj='2011-06-23'
SET @jj='2012-06-22'

SET @str_jk=CONVERT(VARCHAR(10),@jk,120)
SET @str_jj=CONVERT(VARCHAR(10),@jj,120)

DECLARE @WHERE1 NVARCHAR(MAX),@WHERE2 NVARCHAR(MAX),@WHERE3 NVARCHAR(MAX)
SELECT @WHERE1='CONVERT(datetime,srq,112)BETWEEN dateadd(dd,-15,'''+@str_jk+''') AND '''+@str_jk+'''' ,
@WHERE2='CONVERT(datetime,srq,112) BETWEEN '''+@str_jj+''' AND dateadd(dd,15,'''+@str_jj+''')' ,
@WHERE3='CONVERT(datetime,srq,112) BETWEEN dateadd(dd,-15,'''+@str_jk+''') AND dateadd(dd,15,'''+@str_jj+''')

[其他解释]
建议你给出测试数据和表结构 以及你的算法 看看大家写写


光看你的语句 觉得你可以现对这两个表的数据按日期分别汇总 再关联查询处理
[其他解释]
两个表有关联id没?
[其他解释]
(SELECT (SELECT sum(nqhje) FROM t_qhb WHERE CONVERT(datetime,srq,112)BETWEEN @jk AND @jj
AND sspbh NOT IN (SELECT b.GDGID FROM t_ord a,t_orddtl b WHERE a.fildate BETWEEN @jk
AND @jj AND a.num=b.num))
/
(SELECT sum(nchje) FROM t_chb WHERE CONVERT(datetime,srq,112)BETWEEN @jk AND @jj
AND sspbh NOT IN (SELECT b.GDGID FROM t_ord a,t_orddtl b WHERE a.fildate BETWEEN @jk
AND @jj AND a.num=b.num)) AS 不订货缺货率) g

像这样的感觉where后面都重复了。 能不能联合起来写一次?
[其他解释]
2个表没关联的。就是求相同的时间段内的总金额 然后相除。
取的条件都一样。就是2个表都要取一次。重复写感觉语句没效率
[其他解释]
语句长不要紧,只要效率不差就行了,对于同一个表,条件并不重复.应该没办法精简.
[其他解释]


谢谢大家。。
现在问题是我有很多这样的句子每条语句都要取这个条件
程序里面已经超出的字节长度了。必须要精短下。
有没有什么办法可以把那条件写成一个变量
然后我每个语句where 后面就直接加个@sql?
[其他解释]
拼接字符串?
[其他解释]
什么办法都行。能实现就可以。现在就是语句太长了。


引用:
拼接字符串?

[其他解释]
引用:
什么办法都行。能实现就可以。现在就是语句太长了。


引用:拼接字符串?


你给出你的表结构和测试数据 再说说你的算法 我看了你的语句 应该是可以换个写法的
[其他解释]
t_chb 出货表
srq 时间 sspbh 编码 nchsl 数量 nchje 金额
2011060200091251 67.00221.10
2011060201060010 16.00124.80
2011060201090215 60.00378.00
2011060201090239 296.002308.80
2011060201090246 464.001948.80
2011060201090284 924.002698.08
2011060201090321 233.00477.65
t_qhb 去货表
结构一样。就是最后的金额字段换成nqhje。
我就是求缺货表一段时间内sum(金额)再除以出货表的sum(金额)
可能具体取哪段时间哪些编码。2个表都取的一样的条件。就写2次了。。

引用:
引用:
什么办法都行。能实现就可以。现在就是语句太长了。


引用:拼接字符串?

你给出你的表结构和测试数据 再说说你的算法 我看了你的语句 应该是可以换个写法的

[其他解释]
引用:
t_chb 出货表
srq 时间 sspbh 编码 nchsl 数量 nchje 金额
2011060200091251 67.00221.10
2011060201060010 16.00124.80
2011060201090215 60.00378.00
20110602010902……


你这两个表没得关系 汇总时间也不一样 那基本上没法怎么精简了 你的写法也对 我刚刚看成了时间范围是一样的 那样的话就可以精简一下 不好意思
[其他解释]
引用:
引用:
t_chb 出货表
srq 时间 sspbh 编码 nchsl 数量 nchje 金额
20110602 00091251 67.00 221.10
20110602 01060010 16.00 124.80
20110602 01090215 60.00 378.00
201……

不是啊。我汇总时间是一样啊
2个表都是取一样的时间汇总的
[其他解释]
语句长没法拼?
写成三句不就行了:
1.
SELECT (SELECT sum(nqhje) FROM t_qhb WHERE CONVERT(datetime,srq,112)BETWEEN dateadd(dd,-15,@jk) AND @jk) / (SELECT sum(nchje) FROM t_chb WHERE CONVERT(datetime,srq,112)BETWEEN dateadd(dd,-15,@jk) AND @jk) AS 节前15天缺货率

2.
select (SELECT sum(nqhje) FROM t_qhb WHERE CONVERT(datetime,srq,112)BETWEEN @jj AND dateadd(dd,15,@jj)) / (SELECT sum(nchje) FROM t_chb WHERE CONVERT(datetime,srq,112)BETWEEN @jj AND dateadd(dd,15,@jj)) AS 节后15天缺货率



3.
select (SELECT sum(nqhje) FROM t_qhb WHERE CONVERT(datetime,srq,112)BETWEEN dateadd(dd,-15,@jk) AND dateadd(dd,15,@jj)) / (SELECT sum(nchje) FROM t_chb WHERE CONVERT(datetime,srq,112)BETWEEN dateadd(dd,-15,@jk) AND dateadd(dd,15,@jj)) AS 前后30天缺货率
[其他解释]
发帖的这个例子可能不太清楚。
你可以看下3楼的例子。应该能说明我的问题和需求
[其他解释]
更简便的方法,是用6个语句,分别从数据库里求出统计值,然后在你的程序里去求除法.

兄弟,要学会变通.
[其他解释]

引用:
语句长没法拼?
写成三句不就行了:
1.
SELECT (SELECT sum(nqhje) FROM t_qhb WHERE CONVERT(datetime,srq,112)BETWEEN dateadd(dd,-15,@jk) AND @jk) / (SELECT sum(nchje) FROM t_chb WHERE CONVERT(datetime,srq,112)BETWEEN ……

不是的。。
我是把这些结果放进一个select里面。分成3句单独看是短了。但是都得放进程序里面去的。
程序sql字符就超出了。所以希望把每天重复写的条件语句能不能整合起来?或者用一个什么变量代替也行?
[其他解释]
引用:
更简便的方法,是用6个语句,分别从数据库里求出统计值,然后在你的程序里去求除法.

兄弟,要学会变通.

呵呵 。谢谢我以后会注意。
不过现在我是用sql做万能报表 只能用一个select查出这些数据
但是他的报表有sql字数限制。写太长就不行啊
[其他解释]
那,另外建三个函数,计算相应的东西并返回,然后在语句中调用这个函数就行了.
[其他解释]
SELECT sum(b.arvqty*b.price)/sum(b.qty*b.price)  节前后30天订单满足率,
sum(CASE WHEN a.fildate>@jk THEN 0 ELSE b.arvqty END*b.price)/sum
(CASE WHEN a.fildate>@jk THEN 1 ELSE b.qty END*b.price) 节前15天订单满足率
,sum(CASE WHEN a.fildate<@jj THEN 0 ELSE b.arvqty END*b.price)/sum
(CASE WHEN a.fildate<@jj THEN 1 ELSE b.qty END*b.price) 节后15天订单满足率 FROM t_ord a,t_orddtl b
WHERE a.fildate BETWEEN dateadd(dd,-15,@jk) AND dateadd(dd,15,@jj)
AND a.num=b.NUM

像这样的就可以只写一次条件,
但是像发帖例子那样涉及到2个不关联的表怎么办。。求大神啊 别沉啊- -老板要砍人的啊

[其他解释]

各位大大再帮帮忙想想办法啊。感激不尽啊
[其他解释]
谢谢ben,要怎么写呢?
 
DECLARE @qk datetime,@jk datetime
DECLARE @qj datetime,@jj datetime

SET @qk='2011-06-21'SET @jk='2012-06-21'
SET @qj='2011-06-23'SET @jj='2012-06-22'

DECLARE @WHERE1 NVARCHAR(MAX),@WHERE2 NVARCHAR(MAX),@WHERE3 NVARCHAR(MAX)
SELECT @WHERE1='CONVERT(datetime,srq,112)BETWEEN dateadd(dd,-15,@jk) AND @jk' ,
@WHERE2='CONVERT(datetime,srq,112)BETWEEN @jj AND dateadd(dd,15,@jj)' ,
@WHERE3='CONVERT(datetime,srq,112)BETWEEN dateadd(dd,-15,@jk) AND dateadd(dd,15,@jj)'
EXEC (N'SELECT (SELECT sum(nqhje) FROM t_qhb WHERE '+@WHERE1+')


/
(SELECT sum(nchje) FROM t_chb WHERE '+@WHERE1+') AS 节前15天缺货率
,
(SELECT sum(nqhje) FROM t_qhb WHERE '+@WHERE2+')
/ (SELECT sum(nchje) FROM t_chb WHERE '+@WHERE2+') AS 节后15天缺货率 ,
(SELECT sum(nqhje) FROM t_qhb WHERE '+@WHERE3+')
/ (SELECT sum(nchje) FROM t_chb WHERE '+@WHERE3+') AS 前后30天缺货率')
消息 137,级别 15,状态 2,第 1 行
必须声明标量变量 "@jk"。
消息 137,级别 15,状态 2,第 3 行
必须声明标量变量 "@jk"。
消息 137,级别 15,状态 2,第 5 行
必须声明标量变量 "@jj"。
消息 137,级别 15,状态 2,第 6 行
必须声明标量变量 "@jj"。
消息 137,级别 15,状态 2,第 7 行
必须声明标量变量 "@jk"。
消息 137,级别 15,状态 2,第 8 行
必须声明标量变量 "@jk"。


[其他解释]
DECLARE @WHERE1 NVARCHAR(MAX),@WHERE2 NVARCHAR(MAX),@WHERE3 NVARCHAR(MAX)

SELECT @WHERE1='CONVERT(datetime,srq,112)BETWEEN?dateadd(dd,-15,@jk)?AND?@jk'
,@WHERE2='CONVERT(datetime,srq,112)BETWEEN?@jj?AND?dateadd(dd,15,@jj)'
,@WHERE3='CONVERT(datetime,srq,112)BETWEEN?dateadd(dd,-15,@jk)?AND?dateadd(dd,15,@jj)'

EXEC (N'SELECT?(SELECT?sum(nqhje)?FROM?t_qhb?WHERE?
'+@WHERE1+')
/
(SELECT?sum(nchje)?FROM?t_chb?WHERE?
'+@WHERE1+')?AS?节前15天缺货率
,
(SELECT?sum(nqhje)?FROM?t_qhb?WHERE?
'+@WHERE2+')
/
(SELECT?sum(nchje)?FROM?t_chb?WHERE?
'+@WHERE2+')?AS?节后15天缺货率
,
(SELECT?sum(nqhje)?FROM?t_qhb?WHERE?
'+@WHERE3+')
/
(SELECT?sum(nchje)?FROM?t_chb?WHERE?
'+@WHERE3+')?AS?前后30天缺货率'
)

[其他解释]

DECLARE @WHERE1 NVARCHAR(MAX),@WHERE2 NVARCHAR(MAX),@WHERE3 NVARCHAR(MAX)
SELECT @WHERE1='CONVERT(datetime,srq,112)BETWEEN dateadd(dd,-15,'''+CONVERT(VARCHAR(10),@jk,112)+''') AND '''+CONVERT(VARCHAR(10),@jk,112)+'''' ,
@WHERE2='CONVERT(datetime,srq,112) BETWEEN '''+CONVERT(VARCHAR(10),@jj,120)+''' AND dateadd(dd,15,'''+CONVERT(VARCHAR(10),@jj,120)+''')' ,
@WHERE3='CONVERT(datetime,srq,112) BETWEEN dateadd(dd,-15,'''+CONVERT(VARCHAR(10),@jk,120)+''') AND dateadd(dd,15,'''+CONVERT(VARCHAR(10),@jj,120)+''')

[其他解释]
关注SQL的信息。
[其他解释]
谢谢ben
可以实现。不过如果要把这个结果当成一个表然后和别的select静态连接怎么实现比如
selelct * from 
(select * from table ) a,
(select * from table1 ) b,
(exec (N'SELECT (SELECT sum(nqhje) FROM t_qhb WHERE '+@WHERE1+')


/
(SELECT sum(nchje) FROM t_chb WHERE '+@WHERE1+') AS 节前15天缺货率
, (SELECT sum(nqhje) FROM t_qhb WHERE '+@WHERE2+')
/
(SELECT sum(nchje) FROM t_chb WHERE '+@WHERE2+') AS 节后15天缺货率
, (SELECT sum(nqhje) FROM t_qhb WHERE '+@WHERE3+')
/ (SELECT sum(nchje) FROM t_chb WHERE '+@WHERE3+') AS 前后30天缺货率') ) c


类似这样的意思怎么实现?
[其他解释]
,条件并不重复.应该没办法精简
[其他解释]
select * from ( 报表语句 ) t再链接
[其他解释]
如果是 2005 以上的版本 可以用 with 来优化,
否则就麻烦点,多写几个视图。
[其他解释]
列出你的表结构,和数据,说出你的需求和想法,大家帮你想办法
[其他解释]
分开算啊. 检索归检索, 计算归计算

读书人网 >SQL Server

热点推荐