如何从union语句中删除重复的行

时间:2012-06-22 15:20:34

标签: sql sql-server sql-server-2008 sql-server-2008-r2

好的 - 我看了看,发现了很多例子,但没有达到我的需要。也许我用错误的单词搜索,但我可以使用你的帮助。我将提供尽可能详细的信息。

我需要生成一个报表,将两个表中的字段或视图和表合并到一个报表表中。这是我正在使用的声明:

SELECT A.ConfInt, A.Conference, 
        NULL as Ordered,
        NULL as Approved,
        NULL as PickedUp,
        SUM(dbo.Case_Visit_Payments.Qty) AS Qty
FROM         dbo.Conferences as A INNER JOIN
                      dbo.Case_Table ON A.ConfInt = dbo.Case_Table.Conference_ID INNER JOIN
                      dbo.Case_Visit_Payments ON dbo.Case_Table.Case_ID = dbo.Case_Visit_Payments.Case_ID
WHERE     (dbo.Case_Visit_Payments.Item_ID = 15 AND A.ProjectCool = 1)
GROUP BY A.Conference, A.ConfInt
UNION
SELECT  B.ConfInt, 
        B.Conference, 
        SUM(dbo.Cool_Fan_Order.NumberOfFansRequested) AS Ordered, 
        SUM(dbo.Cool_Fan_Order.Qty_Fans_Approved) AS Approved, 
        SUM(dbo.Cool_Fan_Order.Qty_Fans_PickedUp) AS PickedUp, 
        NULL AS Qty
FROM         dbo.Conferences as B LEFT OUTER JOIN
                      dbo.Cool_Fan_Order ON B.ConfInt = dbo.Cool_Fan_Order.Conference_ID
where B.ProjectCool = 1
GROUP BY B.Conference, B.ConfInt

以下是结果:

4   Our Lady        NULL    NULL    NULL    11
4   Our Lady        40      40      40      NULL
7   Holy Rosary     20      20      20      NULL
11  Little Flower   NULL    NULL    NULL    21
11  Little Flower   5       5       20      NULL
19  Perpetual Help  NULL    NULL    NULL    2
19  Perpetual Help  20      20      20      NULL

我更希望的是没有重复的行,例如:

4   Our Lady        40      40      40      11
7   Holy Rosary     20      20      20      NULL
11  Little Flower   5       5       20      21
19  Perpetual Help  20      20      20      2

我希望这个问题足够明确。任何建议将不胜感激。而且我做了回答。 :)

格雷戈里

3 个答案:

答案 0 :(得分:6)

您可以将实际查询用作子查询,对非重复值使用聚合函数(MAX OR SUM),按非聚合列使用

SELECT ConfInt, Conference, MAX(Ordered), MAX(Approved), MAX(PickedUp), MAX(Qty)
FROM (<your actualQuery>)
GROUP BY ConfInt, Conference.

答案 1 :(得分:5)

快速回答是将您的查询包装在另一个中,

SELECT ConfInt
     , Conference
     , SUM(Ordered) AS Ordered
     , SUM(Approved) As Approved
     , SUM(PickedUp) AS PickedUp
     , SUM(Qty) AS Qty
  FROM (

       <your UNION query here>  

      )
 GROUP BY ConfInt, Conference

这不是实现结果集的唯一方法,但它是满足指定要求的最快捷方式。

作为替代方案,我相信这些查询会返回相同的结果:

我们可以在SELECT列表中使用相关子查询来获取Qty:

;WITH q AS
      ( SELECT B.ConfInt
             , B.Conference
             , SUM(o.NumberOfFansRequested) AS Ordered
             , SUM(o.Qty_Fans_Approved) AS Approved
             , SUM(o.Qty_Fans_PickedUp) AS PickedUp
          FROM dbo.Conferences as B
          LEFT
          JOIN dbo.Cool_Fan_Order o ON o.Conference_ID = B.ConfInt
         WHERE B.ProjectCool = 1
         GROUP BY B.ConfInt, B.Conference
      )
 SELECT q.ConfInt
      , q.Conference
      , q.Ordered
      , q.Approved
      , q.PickedUp
      , ( SELECT SUM(v.Qty)
            FROM dbo.Case_Table t
            JOIN dbo.Case_Visit_Payments v ON v.Case_ID = t.Case_ID
           WHERE t.Conference_ID = q.ConfInt
             AND v.Item_ID = 15
        ) AS Qty
   FROM q
  ORDER BY q.ConfInt, q.Conference

或者,我们可以对两个查询使用LEFT JOIN操作,而不是UNION。 (我们知道引用Cool_Fan_Order的查询可以是外连接的左侧,因为我们知道它返回的行数至少与其他查询一样多。(基本上,我们知道其他查询不能返回ConfInt的值和不在Cool_Fan_Order查询中的会议。)

;WITH p AS 
      ( SELECT A.ConfInt
             , A.Conference
             , SUM(v.Qty) AS Qty
          FROM dbo.Conferences as A
          JOIN dbo.Case_Table t ON t.Conference_ID = A.ConfInt
          JOIN dbo.Case_Visit_Payments v ON v.Case_ID = t.Case_ID
         WHERE A.ProjectCool = 1
           AND v.Item_ID = 15
         GROUP BY A.ConfInt, A.Conference
      )
    , q AS
      ( SELECT B.ConfInt
             , B.Conference
             , SUM(o.NumberOfFansRequested) AS Ordered
             , SUM(o.Qty_Fans_Approved) AS Approved
             , SUM(o.Qty_Fans_PickedUp) AS PickedUp
          FROM dbo.Conferences as B
          LEFT
          JOIN dbo.Cool_Fan_Order o ON B.ConfInt = o.Conference_ID
         WHERE B.ProjectCool = 1
         GROUP BY B.ConfInt, B.Conference
      )
 SELECT q.ConfInt
      , q.Conference
      , q.Ordered
      , q.Approved
      , q.PickedUp
      , p.Qty
   FROM q
   LEFT
   JOIN p ON p.ConfInt = q.ConfInt AND p.Conference = q.Conference
  ORDER BY q.ConfInt, q.Conference

这三者之间的选择(他们都在所有条件下返回相同的结果集),归结为可读性和可维护性以及性能。在足够大的行集上,三个语句之间可能存在一些可观察到的性能差异。

答案 2 :(得分:0)

我只是在第一个选择中将连接放到Cool_Fan_Order并删除联合。

这会返回相同的结果吗?

 select
        A.ConfInt,
        A.Conference,
        sum(dbo.Cool_Fan_Order.NumberOfFansRequested) as Ordered,
        sum(dbo.Cool_Fan_Order.Qty_Fans_Approved) as Approved,
        sum(dbo.Cool_Fan_Order.Qty_Fans_PickedUp) as PickedUp,
        sum(sub.Qty) as Qty
    from
        dbo.Conferences as A
        left outer join 
        (
            select
                c.ConfInt,
                cvp.Qty
            from dbo.Conferences c
                inner join dbo.Case_Table ct
                    on a.confInt=ct.Conference_ID
                inner join dbo.Case_Visit_Payments cvp
                    on ct.Case_ID=cvp.Case_ID
            where cvp.Item_ID=15
        ) sub
            on a.ConfInt=sub.ConfInt
        left outer join dbo.Cool_Fan_Order
            on A.ConfInt = dbo.Cool_Fan_Order.Conference_ID
    where
        (
         A.ProjectCool = 1
        )
    group by
        A.Conference,
        A.ConfInt