以文本方式查看主题 - Foxtable(狐表) (http://foxtable.com/bbs/index.asp) -- 专家坐堂 (http://foxtable.com/bbs/list.asp?boardid=2) ---- 多表联合查询where条件的问题 (http://foxtable.com/bbs/dispbbs.asp?boardid=2&id=121030) |
-- 作者:happyft -- 发布时间:2018/6/27 18:53:00 -- 多表联合查询where条件的问题 项目的进出仓单据有二十种左右,现在为了查询某个产品的出入库明细信息,将二十个表用union all连接起来再通过统一的where条件查询, 现在数据量有近百万,有时速度非常慢,想把where条件先传入到每个表的查询中最后再union all在一起,这样是否快些? 但问题来了,原来设计时没考虑这点,所以各个表中的字段取名不一致,比如日期有入库日期,出库日期,报废日期等,现在如果要传入给每个表的查询where条件用却无法实现了,查询窗口中只有一个日期字段,这个传入的日期参数无法通用于每张单,除了将每个基表的日期字段改为相同名字外,还有没有其他办法? 谢谢! |
-- 作者:有点甜 -- 发布时间:2018/6/27 20:31:00 -- union all 会生成一个临时表,把所需的数据填充到这个表格的,数据量越大,肯定就越慢。
你现在这种情况,就动态合成sql语句呗。定义好每个表对应的日期字段分别是什么,然后分别合成select语句加上where条件,最后union。 |
-- 作者:HappyFt -- 发布时间:2018/6/28 11:28:00 -- 在ft中,每个表动态合成sql语句后可以用AppendLine()每条加在一起最后统一执行,如果直接在sql的储存过程中是不是每个表拼接好sql语句后像下面这样: Declare
@Sql nvarchar(max),@Sql2 nvarchar(max) IF
@tbn = \'表1\' Begin Se t @Sql2=\'.....\' Se t @Sql=@Sql+@sql2 End elseif @tbn = \'表2\' Begin Se t @Sql2=\'.....\' Se t @Sql=@Sql+@sql2 end 最后Exec (@Sql)
|
-- 作者:有点甜 -- 发布时间:2018/6/28 11:31:00 -- 是要分别判断在where那里合成不同条件的,把所有sql语句最后union在一起运行即可。 |
-- 作者:HappyFt -- 发布时间:2018/6/28 11:50:00 -- 分别合成where条件这个明白, 我是想问如何将每一个包括不同where条件的sql语句union 在一起 Se t @Sql2=\'..... + \'union all\' + char(10) Se t @Sql=@Sql+@sql2 这样的方式不可以吗? |
-- 作者:有点甜 -- 发布时间:2018/6/28 13:32:00 -- 你现在这样做有什么问题?字符串无法合并起来? |
-- 作者:HappyFt -- 发布时间:2018/6/28 17:44:00 -- 做是做出来了,为什么先where查询后再union所有表的速度与全部表union后后再where的速度差不多呢? |
-- 作者:有点甜 -- 发布时间:2018/6/28 18:06:00 -- 以下是引用HappyFt在2018/6/28 17:44:00的发言:
做是做出来了,为什么先where查询后再union所有表的速度与全部表union后后再where的速度差不多呢?
数据量相差多少?假如全部表数据有100万行,加入where条件后是100行数据,运行看速度变化。 |
-- 作者:HappyFt -- 发布时间:2018/6/28 18:44:00 -- 直接在sql里面执行查询的数据,都是远程数据库 SE LECT [_Identify], [sys_Fzt], [sys_Over], [进出单号], [进出日期], [进出单位], [仓库], [仓管员], [产品编码], [来源单号], [品名], [规格], [工序号], [入库数量], [出库数量], [进出数量], [计量单位], [品质判定], [进出类别], [盘点序号], [品质状态] FROM [dbo].[uv_ck110] --uv_ck110这个视图就是没有where条件将每个表数据直接union的 WHERE 进出日期 > \'2018-06-26\' 上面是直接在后面加条件的查询 , 而先用了where条件再union的是通过调用储存过程来测试的如下: EXEC @return_value = [dbo].[usp_kcinout] @whereflt = N\'进出日期 > \'\'2017-06-26\'\'\' 用了2018-06-26,2017-06-26,2014-06-26三个日期分别执行查询出来的数据时间都是差不多的 1199条/1秒内,20万/29秒,70万/1分48秒 是不是我的动态sql语句拼接的不正确啊,但又没发现哪里有错,sql语句如下(共有23个表中查询) @whereflt是传入条件 DECLARE @sql NVARCHAR(MAX); DECLARE @sql2 NVARCHAR(MAX); DECLARE @flt NVARCHAR(400); SE T @flt = REPLACE(@whereflt, \'进出日期\', \'入库日期\'); --替换进出日期 SE T @sql2 = \' SE LECT a._Identify , a.sys_Fzt , b.sys_Over , b.入库单号 AS 进出单号 , a.入库日期 AS 进出日期 , a.入库单位 AS 进出单位 , a.仓库 , a.仓管员 , b.产品编码 , b.来源单号 , b.品名 , b.规格 , 0 AS 工序号 , b.数量 AS 入库数量 , 0 AS 出库数量 , b.数量 AS 进出数量 , b.计量单位 , 品质判定 , \'\'采购入库\'\' AS 进出类别 , 0 AS 盘点序号 , CASE WHEN b.品质判定 IN ( \'\'合格\'\', \'\'特采\'\' ) THEN \'\'合格品\'\' WHEN b.品质判定 IN ( \'\'选别\'\', \'\'退货\'\' ) THEN \'\'不良品\'\' WHEN b.品质判定 = \'\'报废\'\' THEN \'\'报废品\'\' ELSE \'\'待检品\'\' END AS 品质状态 FROM 采购入库单 a INNER JOIN 采购入库明细 b ON a.入库单号 = b.入库单号 where \' + @flt; SE T @sql = @sql2 + \'Union all \' + CHAR(10); SE T @flt = REPLACE(@whereflt, \'进出日期\', \'退货日期\'); --替换进出日期 SE T @sql2 = \' SE LECT a._Identify , a.sys_Fzt , b.sys_Over , b.退货单号 AS 进出单号 , a.退货日期 AS 进出日期 , a.收货单位 AS 进出单位 , a.仓库 , a.仓管员 , b.产品编码 , b.来源单号 , b.品名 , b.规格 , 0 AS 工序号 , -b.数量 AS 入库数量 , 0 AS 出库数量 , -b.数量 AS 进出数量 , b.计量单位 , 品质状态 , \'\'采购退货\'\' AS 进出类别 , 0 AS 盘点序号 , CASE WHEN b.品质状态 = \'\'合格品\'\' THEN \'\'合格品\'\' WHEN b.品质状态 = \'\'不良品\'\' THEN \'\'不良品\'\' WHEN b.品质状态 = \'\'报废品\'\' THEN \'\'报废品\'\' ELSE \'\'待检品\'\' END AS 品质状态 FROM dbo.采购退货单 AS a INNER JOIN 采购退货明细 AS b ON a.退货单号 = b.退货单号 where \' + @flt; SE T @sql = @sql + @sql2 + \'Union all \' + CHAR(10); 其他表相同,最后再 EXEC sp_executesql @sql |
-- 作者:有点甜 -- 发布时间:2018/6/28 21:56:00 -- 如果执行 1199条/1秒内 的话,说明没有区别。
耗时不在where条件,而在拷贝数据到临时表那个操作。因为20万条的时候耗时较多。
一般在foxtable显示的时候,不需要全部显示过来吧?如果只是显示少量,加上top取少量数据试试。 |