Foxtable(狐表)用户栏目专家坐堂 → 多表联合查询where条件的问题


  共有4746人关注过本帖树形打印复制链接

主题:多表联合查询where条件的问题

帅哥哟,离线,有人找我吗?
happyft
  1楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:八尾狐 帖子:1934 积分:17661 威望:0 精华:0 注册:2014/7/29 19:09:00
多表联合查询where条件的问题  发帖心情 Post By:2018/6/27 18:53:00 [只看该作者]

项目的进出仓单据有二十种左右,现在为了查询某个产品的出入库明细信息,将二十个表用union all连接起来再通过统一的where条件查询,
现在数据量有近百万,有时速度非常慢,想把where条件先传入到每个表的查询中最后再union all在一起,这样是否快些?
但问题来了,原来设计时没考虑这点,所以各个表中的字段取名不一致,比如日期有入库日期,出库日期,报废日期等,现在如果要传入给每个表的查询where条件用却无法实现了,查询窗口中只有一个日期字段,这个传入的日期参数无法通用于每张单,除了将每个基表的日期字段改为相同名字外,还有没有其他办法?

谢谢!


 回到顶部
帅哥哟,离线,有人找我吗?
有点甜
  2楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:版主 帖子:85326 积分:427815 威望:0 精华:5 注册:2012/10/18 22:13:00
  发帖心情 Post By:2018/6/27 20:31:00 [只看该作者]

union all 会生成一个临时表,把所需的数据填充到这个表格的,数据量越大,肯定就越慢。

 

你现在这种情况,就动态合成sql语句呗。定义好每个表对应的日期字段分别是什么,然后分别合成select语句加上where条件,最后union。


 回到顶部
帅哥哟,离线,有人找我吗?
HappyFt
  3楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:八尾狐 帖子:1934 积分:17661 威望:0 精华:0 注册:2014/7/29 19:09:00
  发帖心情 Post By: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)




 回到顶部
帅哥哟,离线,有人找我吗?
有点甜
  4楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:版主 帖子:85326 积分:427815 威望:0 精华:5 注册:2012/10/18 22:13:00
  发帖心情 Post By:2018/6/28 11:31:00 [只看该作者]

是要分别判断在where那里合成不同条件的,把所有sql语句最后union在一起运行即可。


 回到顶部
帅哥哟,离线,有人找我吗?
HappyFt
  5楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:八尾狐 帖子:1934 积分:17661 威望:0 精华:0 注册:2014/7/29 19:09:00
  发帖心情 Post By:2018/6/28 11:50:00 [只看该作者]

分别合成where条件这个明白, 我是想问如何将每一个包括不同where条件的sql语句union 在一起
Se t @Sql2='..... + 'union all' + char(10)

Se t @Sql=@Sql+@sql2


这样的方式不可以吗?


 回到顶部
帅哥哟,离线,有人找我吗?
有点甜
  6楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:版主 帖子:85326 积分:427815 威望:0 精华:5 注册:2012/10/18 22:13:00
  发帖心情 Post By:2018/6/28 13:32:00 [只看该作者]

你现在这样做有什么问题?字符串无法合并起来?

 回到顶部
帅哥哟,离线,有人找我吗?
HappyFt
  7楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:八尾狐 帖子:1934 积分:17661 威望:0 精华:0 注册:2014/7/29 19:09:00
  发帖心情 Post By:2018/6/28 17:44:00 [只看该作者]

做是做出来了,为什么先where查询后再union所有表的速度与全部表union后后再where的速度差不多呢?

 回到顶部
帅哥哟,离线,有人找我吗?
有点甜
  8楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:版主 帖子:85326 积分:427815 威望:0 精华:5 注册:2012/10/18 22:13:00
  发帖心情 Post By:2018/6/28 18:06:00 [只看该作者]

以下是引用HappyFt在2018/6/28 17:44:00的发言:
做是做出来了,为什么先where查询后再union所有表的速度与全部表union后后再where的速度差不多呢?

 

数据量相差多少?假如全部表数据有100万行,加入where条件后是100行数据,运行看速度变化。


 回到顶部
帅哥哟,离线,有人找我吗?
HappyFt
  9楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:八尾狐 帖子:1934 积分:17661 威望:0 精华:0 注册:2014/7/29 19:09:00
  发帖心情 Post By: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



 回到顶部
帅哥哟,离线,有人找我吗?
有点甜
  10楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:版主 帖子:85326 积分:427815 威望:0 精华:5 注册:2012/10/18 22:13:00
  发帖心情 Post By:2018/6/28 21:56:00 [只看该作者]

如果执行 1199条/1秒内 的话,说明没有区别。

 

耗时不在where条件,而在拷贝数据到临时表那个操作。因为20万条的时候耗时较多。

 

一般在foxtable显示的时候,不需要全部显示过来吧?如果只是显示少量,加上top取少量数据试试。


 回到顶部
总数 12 1 2 下一页