【问题标题】:Union All Won't work in stored procedureUnion All 在存储过程中不起作用
【发布时间】:2010-12-23 17:19:05
【问题描述】:
ALTER PROCEDURE [dbo].[MyStoredProcedure1]
 @YearToGet int

AS
Select Division, SDESCR,        
    DYYYY, 
 Sum(APRICE) ASofSales, 
    Sum(PARTY) AS ASofPAX,        
    Sum(NetAmount) ASofNetSales,        
    Sum(InsAmount) ASofInsSales,        
    Sum(CancelRevenue) ASofCXSales,        
    Sum(OtherAmount) ASofOtherSales,        
    Sum(CXVALUE) ASofCXValue  
From dbo.B101BookingsDetails 
Where Booked <= CONVERT(int,DateAdd(year, @YearToGet - Year(getdate()),                   
                DateAdd(day, DateDiff(day, 1, getdate()), 0) ) ) and
(DYYYY = @YearToGet)
Group By SDESCR, DYYYY, Division
Having (DYYYY = @YearToGet)  
Order By Division, SDESCR, DYYYY 

union all

SELECT     
DIVISION, 
SDESCR,
DYYYY, 
SUM(APRICE) AS YESales, 
SUM(PARTY) AS YEPAX, 
SUM(NetAmount) AS YENetSales,
SUM(InsAmount)  AS YEInsSales, 
SUM(CancelRevenue) AS YECXSales, 
SUM(OtherAmount) AS YEOtherSales,
SUM(CXVALUE) AS YECXValue
FROM         dbo.B101BookingsDetails 
Where (DYYYY=@YearToGet)
GROUP BY SDESCR, DYYYY, DIVISION
ORDER BY DIVISION, SDESCR, DYYYY

我得到的错误是

消息 156,级别 15,状态 1,程序 MyStoredProcedure1,第 36 行不正确 关键字“union”附近的语法。

但我的目标是用户输入一年,例如 2009 年,我的第一个查询将获取 2009 年到昨天 2009 年 12 月 23 日同一日期的所有销售额,而第二个查询将获取 2009 年的总数截至 2009 年 12 月 31 日。

我希望列并排而不是在一列中

【问题讨论】:

  • 你得到的错误信息是?你的问题是???
  • 当你试图将它们与UNION ALL 组合在一起时,我认为你不能在你的部分SELECT 上使用ORDER BY;尝试从第一个 SELECT 中删除 ORDER BY - 那么它可以工作吗?
  • 你是对的,marc 但由于某种原因,所有内容都显示在同一列中,例如 YESales 和 AsofSales 仍在同一列下
  • 您确定要在此处使用联合吗?您真的希望该过程返回两个单独的记录集吗?
  • 如果它返回两个单独的记录集,它在网格视图中是如何工作的

标签: sql-server sql-server-2005 stored-procedures


【解决方案1】:

如果您想并排显示数据,那么您不想使用 UNION。相反,您可以使用派生表或 CTE,然后加入 SDESC、DYYYY、Division 上的 2 个查询。查看您的查询,唯一(明显)的区别是一个在 Booked 列上包含 where 子句。我们可以将这个 where 子句标准移动到 sum 聚合中,这应该允许我们一次通过表获得我们需要的所有数据。像这样的:

ALTER PROCEDURE [dbo].[MyStoredProcedure1]
 @YearToGet int
AS
SET NOCOUNT ON

Declare @Booked Int
Set @Booked = CONVERT(int,DateAdd(year, @YearToGet - Year(getdate()),                   
                DateAdd(day, DateDiff(day, 1, getdate()), 0) ) )

Select Division, 
       SDESCR,        
       DYYYY, 
       Sum(Case When Booked <= @Booked Then APRICE End) ASofSales, 
       SUM(APRICE) AS YESales, 

       Sum(Case When Booked <= @Booked Then PARTY End) AS ASofPAX,        
       SUM(PARTY) AS YEPAX, 

       Sum(Case When Booked <= @Booked Then NetAmount End) ASofNetSales,        
       SUM(NetAmount) AS YENetSales,

       Sum(Case When Booked <= @Booked Then InsAmount End) ASofInsSales,        
       SUM(InsAmount)  AS YEInsSales, 

       Sum(Case When Booked <= @Booked Then CancelRevenue End) ASofCXSales,        
       SUM(CancelRevenue) AS YECXSales, 

       Sum(Case When Booked <= @Booked Then OtherAmount End) ASofOtherSales,        
       SUM(OtherAmount) AS YEOtherSales,

       Sum(Case When Booked <= @Booked Then CXVALUE End) ASofCXValue,
       SUM(CXVALUE) AS YECXValue
From   dbo.B101BookingsDetails 
Where  DYYYY = @YearToGet
Group By SDESCR, DYYYY, Division
Order By Division, SDESCR, DYYYY 

我鼓励您尝试此程序。我认为它会返回您正在寻找的数据。

已编辑以将小于或等于预订条件。

【讨论】:

  • 啊,如此接近,但我的 asof 列正在重新调整空值:/
  • 你注意到我声明了一个局部变量并将它设置在过程的顶部吗?
  • 我刚刚注意到原来的 where 子句的 Booked 小于或等于。在我的帖子中改变它。很抱歉造成混乱。
  • 耶!我希望我能把这个提高到 1000
【解决方案2】:

删除union all 之前的第一个order by。为了理智起见,请保持列名相同。第二个order by 适用于所有行。

顺便说一句,你想要的更接近这个。没有测试,但根据您的描述,这应该很接近。

;
with
q_00 as (
select
      DIVISION
    , SDESCR
    , DYYYY
    , sum(APRICE)        as ofSales 
    , sum(PARTY)         as ofPAX        
    , sum(NetAmount)     as ofNetSales        
    , sum(InsAmount)     as ofInsSales        
    , sum(CancelRevenue) as ofCXSales        
    , sum(OtherAmount)   as ofOtherSales        
    , sum(CXVALUE)       as ofCXValue  
from dbo.B101BookingsDetails 
where Booked <= CONVERT(int,DateAdd(year, @YearToGet - Year(getdate()), DateAdd(day, DateDiff(day, 1, getdate()), 0)))
  and DYYYY = @YearToGet
group by DIVISION, SDESCR, DYYYY 
),
q_01 as (
select     
      DIVISION 
    , SDESCR
    , DYYYY 
    , sum(APRICE)        as YESales 
    , sum(PARTY)         as YEPAX 
    , sum(NetAmount)     as YENetSales
    , sum(InsAmount)     as YEInsSales 
    , sum(CancelRevenue) as YECXSales 
    , sum(OtherAmount)   as YEOtherSales
    , sum(CXVALUE)       as YECXValue
from  dbo.B101BookingsDetails 
where DYYYY=@YearToGet
group by DIVISION, SDESCR, DYYYY 
)
select
      a.DIVISION 
    , a.SDESCR
    , a.DYYYY
    , ofSales 
    , ofPAX        
    , ofNetSales        
    , ofInsSales        
    , ofCXSales        
    , ofOtherSales        
    , ofCXValue  
    , YESales 
    , YEPAX 
    , YENetSales
    , YEInsSales 
    , YECXSales 
    , YEOtherSales
    , YECXValue
from q_00 as a
join q_01 as b on (b.DIVISION = a.DIVISION and b.SDESCR = a.SDESCR and b.DYYYY = a.DYYYY) 
order by a.DIVISION, a.SDESCR, a.DYYYY ;

【讨论】:

  • 对我来说是一个 sql tard。为什么我得到一个错误;第一行
  • @MyHeadHurts,公用表表达式 (CTE) 需要分号。 CTE 是在 SQL2005 中首次引入的。如果你使用的是 SQL2000,那么你会得到一个错误。如果您使用的是 SQL2000,那么您应该在所有问题中包含该信息。 SQL2000 和更新的版本有不少区别。
  • @MyHeadHurts,抱歉没有正确理解上一个问题——您使用的是 SQL Server 2005 作为标记?
【解决方案3】:

这里的问题不是 UNION ALL 或者列别名的名称不同。问题在于 UNION ALL 行上方的 ORDER BY 行。如果您删除该行,您的查询将运行。这不会像您想要的那样并排列出数据,但它会允许查询运行。

【讨论】:

    【解决方案4】:

    UNION 的要求包括数据类型相似,每个SELECT 包含相同数量的列,并且这些列在两个SELECTs 中以相同的顺序出现。

    编辑:在评论中回答您的问题:如果您想让列并排显示,您必须在两个 SELECT 中放置填充列。

    Select Division, SDESCR, DYYYY, 
    Sum(APRICE) ASofSales, 
    '' AS YESales,
    Sum(PARTY) AS ASofPAX,  
    '' AS YEPAX
    

    ... 以此类推,SELECTS 中的列相同,SELECT 或另一个中的某些列为空。

    另一个编辑: 两个 SELECTS 中的列名(或别名)不必相同,但使用不同的别名将帮助您区分哪一列。在聚合字段 (SU​​M) 上,如果您不提供别名,那么弄清楚该列代表什么可能会很棘手。如果您像在 SQL 中所做的那样对列进行别名,并交错空字符串列,我想您会得到您想要的结果。

    【讨论】:

    • 即使我希望它们并排而不是在彼此下方列出,这是否也是?
    • 名称不同,它们可以是不同的名称,但必须是相同的顺序和字段数并且具有兼容的类型
    • 如此接近,我仍然使用不同的名称,但是当我认为它可以工作时,我就被这个错误击中了 Msg 8114,Level 16,State 5,Procedure MyStoredProcedure1,Line 22 转换数据时出错输入 varchar 到数字。
    • 我的头也开始疼了。我相信您总共应该有 17 列。也许开始更简单,并尝试让前几列工作。然后当它工作时,添加其余的列。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-28
    • 1970-01-01
    • 2013-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多