简体   繁体   English

Union All在存储过程中不起作用

[英]Union All Won't work in stored procedure

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

The error I am getting is 我得到的错误是

Msg 156, Level 15, State 1, Procedure MyStoredProcedure1, Line 36 Incorrect syntax near the keyword 'union'. 消息156,级别15,状态1,过程MyStoredProcedure1,第36行关键字'union'附近的语法不正确。

But my goal here is the user inputs a year for example 2009, my first query will get all the sales made in 2009 to the same date it is was yesterday 12/23/2009, while the second query is getting 2009 totals up to dec 31 2009. 但是我的目标是用户输入一个年份,例如2009年,我的第一个查询将获得与昨天(2009年12月23日)相同日期的2009年所有销售额,而第二个查询将得出2009年的总数2009年3月31日。

I want the columns to be side by side not in one column 我希望各列并排而不是在一列中

If you want to show the data side by side, then you don't want to use UNION. 如果要并排显示数据,则不想使用UNION。 Instead, you could use derived tables or CTE's and then join the 2 queries on SDESCR, DYYYY, Division. 相反,您可以使用派生表或CTE,然后在SDESCR,DYYYY,Division上联接这两个查询。 Looking at your queries, the only (apparent) difference is that one includes a where clause on the Booked column. 查看您的查询,唯一的(明显的)区别是在Booked列上包含where子句。 We can move this where clause criteria in to the sum aggregate which should allow us to get all of the data we need in one pass through the tables. 我们可以将此where子句条件移至总和中,这将使我们能够通过表一次就获得我们需要的所有数据。 Something like this: 像这样:

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 

I encourage you to try this procedure. 我鼓励您尝试此过程。 I think it will return the data you are looking for. 我认为它将返回您正在寻找的数据。

Edited to put Less than or equal for the Booked criteria. 编辑以将“小于或等于”作为“预订”条件。

Remove the first order by , just before the union all . 删除union all之前的第一个order by For sanity, keep the column names the same. 为了保持理智,请保持列名相同。 The second order by applies to all the rows. order by适用于所有行。

BTW , what you want is much closer to this. 顺便说一句 ,您想要的更接近此。 Did not test it, but based on your description this should be close. 没有测试它,但是根据您的描述,它应该很接近。

;
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 ;

Requirements for UNION include that the data types be similar, that each SELECT contains the same number of columns, and that the columns appear in the same order in both SELECT s. 对UNION的要求包括数据类型必须相似,每个SELECT包含相同数量的列,并且两个SELECT中的列以相同的顺序出现。

Edit : to answer your question in a comment: If you want to have the columns appear side by side, you have to put filler columns in both SELECTs. 编辑 :在评论中回答您的问题:如果要使列并排显示,则必须在两个SELECT中都放入填充列。

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

... and so on, with identical columns in both SELECTS , just some columns are empty in one SELECT or the other. ...依此类推,两个SELECTS列相同,只有一个列在另一个SELECT为空。

Another edit: The column names (or aliases) don't have to be the same in both SELECTS, but using different aliases will help you to distinguish which column is which. 另一个编辑:两个SELECTS中的列名(或别名)不必相同,但是使用不同的别名将有助于您区分哪个列。 On the aggregate fields (SUM), if you don't supply an alias, figuring out what the column represents could be tricky. 在汇总字段(SUM)上,如果不提供别名,则弄清楚列表示的内容可能会很棘手。 If you alias the columns as you have done in your SQL, and interleave the empty string columns, I think you will get the result you seek. 如果像在SQL中一样对列进行别名,并交织空字符串列,我认为您将获得想要的结果。

The problem here is not the UNION ALL or that the column aliases are not named the same. 这里的问题不是UNION ALL或列别名的名称不同。 The problem is with the ORDER BY line just above the UNION ALL line. 问题在于UNION ALL行上方的ORDER BY行。 If you remove that line, your query will run. 如果删除该行,则查询将运行。 This won't list the data side by side like you wanted, but it will allow the query to run. 这不会像您想要的那样并排列出数据,但是它将允许查询运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM