T-SQL;将四个查询合并为一行

时间:2014-02-28 19:19:31

标签: sql sql-server-2008-r2

我需要将四个查询返回到单行。我试图自己提出一个内联视图,但一直遇到错误或执行时间很长。我需要将四个值返回到一行以生成库存周转报告。库存退货的公式是收到的单位总数/期末余额* 12.

使用的查询...

Declare @startdate datetime = cast(DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)as Date)
Declare @enddate datetime = cast(DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())+1, 0)as Date)

Select sum(act_quantity) as QtyReceived, podet.wh_num
FROM [irms_2_5_2].[dbo].[podet]
WHERE delivery between @startdate and @enddate
  and wh_num = 'HM10'
Group by podet.wh_num

Select sum(qty) as QtyShipped, pick.wh_num
FROM pick
WHERE convert(datetime, left(date_time,8),102) between @startdate and @enddate
  and wh_num = 'HM10'
Group by pick.wh_num

Select sum(item_qty-sugg_qty) as Adjustments, auditlog.wh_num
FROM auditlog
WHERE wh_num = 'hm10'
  and trans_type = 'as'
  and convert(datetime, left(date_time,8),102) between @startdate and @enddate
Group by auditlog.wh_num


Select sum(total_qty) as endBalance, inventory.wh_num
FROM inventory
WHERE wh_num = 'HM10'
Group by inventory.wh_num

enter image description here

3 个答案:

答案 0 :(得分:2)

到达那里有多种方式。哪种方法最适合您的情况取决于您的数据库,架构和数据的形状。

<强> UNION ALL

这是使用union all的一种方法。根据您的数据的大小和形状,这可以很好地执行,虽然我在SQL Server与大工会的并行性问题上遇到了问题:

select wh_num      = t. wh_num ,
       QtyReceived = sum(           t.act_quantity             ) ,
       QtyShipped  = sum(           t.qty                      ) ,
       Adjustments = sum( coalesce( t.item_qty-t.sugg_qty , 0) ) ,
       endBalance  = sum(           t.total_qty                )
from (  select wh_num       = wh_num ,
               act_quantity = convert(int, act_quantity ) ,
               qty          = convert(int, null         ) ,
               item_qty     = convert(int, null         ) ,
               sugg_qty     = convert(int, null         ) ,
               total_qty    = convert(int, null         )
         from irms_2_5_2.dbo.podet
         where wh_num = 'hm10'
           and delivery between @startdate and @enddate
       UNION ALL
         select wh_num       = wh_num ,
                act_quantity = null   ,
                qty          = qty    ,
                item_qty     = null   ,
                sugg_qty     = null   ,
                total_qty    = null
         from pick
         where wh_num = 'hm10'
           and convert(datetime, left(date_time,8),102) between @startdate and @enddate
       UNION ALL
         select wh_num       = wh_num   ,
                act_quantity = null     ,
                qty          = null     ,
                item_qty     = item_qty ,
                sugg_qty     = sugg_qty ,
                total_qty    = null     
         from auditlog
         where wh_num        = 'hm10'
           and trans_type    = 'as'
           and convert(datetime, left(date_time,8),102) between @startdate and @enddate
       UNION ALL
         select wh_num       = wh_num    ,
                act_quantity = null      ,
                qty          = null      ,
                item_qty     = null      ,
                sugg_qty     = null      ,
                total_qty    = total_qty
         from inventory
         where wh_num = 'hm10'
     ) t
group by t.wh_num

<强> LEFT JOIN

使用left join派生表的另一种方法:

select wh_num      = desired.wh_num ,
       QtyReceived = sum(coalesce( t1.QtyReceived , 0 )) ,
       QtyShipped  = sum(coalesce( t2.QtyShipped  , 0 )) ,
       Adjustments = sum(coalesce( t3.Adjustments , 0 )) ,
       EndBalance  = sum(coalesce( t4.EndBalance  , 0 ))  
from      ( select wh_num = 'hm10' ) desired
left join ( select wh_num      ,
                   QtyReceived = sum(act_quantity)
            from irms_2_5_2.dbo.podet
            where delivery between @startdate and @enddate
            group by wh_num
          ) t1 on t1.wh_num = desired.wh_num
left join ( select wh_num     ,
                   QtyShipped = sum(qty)
            from pick
            where convert(datetime, left(date_time,8),102) between @startdate and @enddate
            group by wh_num
          ) t2 on t2.wh_num = desired.wh_num
left join ( select wh_num      ,
                   Adjustments = sum(item_qty-sugg_qty)
            from auditlog
            where trans_type = 'as'
              and convert(datetime, left(date_time,8),102) between @startdate and @enddate
            group by wh_num
          ) t3 on t3.wh_num = desired.wh_num
left join ( Select wh_num     ,
                   EndBalance = sum(total_qty)
            FROM inventory
            group by wh_num
          ) t4 on t4.wh_num = desired.wh_num
group by desired.wh_num

相关子查询

使用相关子查询的第三种方法

select wh_num      = desired.wh_num ,
       QtyReceived = ( select sum(coalesce( act_quantity , 0 ))
                       from irms_2_5_2.dbo.podet
                       where wh_num   = desired.wh_num
                         and delivery between @startdate and @enddate
                     ) ,
       QtyShipped  = ( select QtyShipped = sum(coalesce( qty , 0 ))
                       from pick
                       where wh_num = desired.wh_num
                         and convert(datetime, left(date_time,8),102) between @startdate and @enddate
                     ) ,
       Adjustments = ( select Adjustments = sum(coalesce( item_qty-sugg_qty , 0 ))
                       from auditlog
                       where wh_num     = desired.wh_num
                         and trans_type = 'as'
                         and convert(datetime, left(date_time,8),102) between @startdate and @enddate
                     ) ,
       EndBalance  = ( Select sum(total_qty)
                       from inventory
                       where wh_num = desired.wh_num
                     )
from ( select wh_num = 'hm10' ) desired

最后一种方法,当您在数据库中存在大量争用并希望最大限度地减少关于锁的查询占用空间时,这种方法很有用,就是创建一个临时表,其中包含最终结果的正确列数设置:

declare @work table
(
  wh_num       varchar(32) not null ,
  QtyReceived  int         not null ,
  QtyShipped   int         not null ,
  Adjustments  int         not null ,
  EndBalance   int         not null  
)

然后单独计算每个值,在工作表中插入一个新行,即:

insert @work (wh_num,QtyReceived)
select 'hm10' ,
       sum(coalesce( act_quantity , 0 ))
from irms_2_5_2.dbo.podet
where wh_num   = 'hm10'
and delivery between @startdate and @enddate

表格完全填充后,将几行汇总为一行以返回结果集:

select wh_num ,
       QtyReceived = sum(QtyReceived) ,
       ...
from @work
group by wh_num

并非每个查询都可以填充T-SQL变量:

declare @QtyReceived int

set @QtyReceived = ( select sum(...) from podet where wh_num = 'hm10' )
...

使用final table-less选择返回最终结果集:

select wh_num      = 'hm10' ,
       QtyReceived = @QtyReceived ,
       ...

有很多不同的方法可以做到这一点。您只需要找到最适合您特定情况的那个。

答案 1 :(得分:1)

只需定义四个变量,为它们赋值并在最后选择它们。对于Ex:

DECLARE @QtyReceived INT,
        @QtyShipped INT,
        @Adjustments INT,
        @EndBalance INT

SELECT @QtyReceived = Sum(act_quantity)
FROM ...
...
SELECT @EndBalance = Sum(total_qty)
FROM ...

SELECT  @QtyReceived QtyReceived, @QtyShipped QtyShipped, @Adjustments Adjustments,
        @EndBalance EndBalance

答案 2 :(得分:0)

通过UNION生成结果集。那么做subselect如下:

以一致的形式生成原始数据:

SELECT * 
INTO #temp
FROM
(
Select sum(act_quantity) as [QTY], podet.wh_num AS [NUM], 'QtyReceived' AS [TYPE]
FROM [irms_2_5_2].[dbo].[podet]
WHERE delivery between @startdate and @enddate
      and wh_num = 'HM10'
Group by podet.wh_num
UNION ALL
Select sum(qty) as [QTY], pick.wh_num AS [NUM], 'QtyShipped' AS [TYPE]
FROM pick
WHERE convert(datetime, left(date_time,8),102) between @startdate and @enddate
      and wh_num = 'HM10'
Group by pick.wh_num
UNION ALL
....<REST OF YOUR STUFF, SIMILAR MANNER
) AS RAW

SELECT
(SELECT Qty FROM #TEMP WHERE Type='QtyShipped') AS QTYShipped,
(SELECT Qty FROM #TEMP WHERE Type='QtyReceived') AS QTYReceived,
...
...