SQL Multiple Selects - 堆叠多个视图并删除重复项

时间:2013-03-01 13:04:36

标签: sql sql-server-2008

我有7个视图,它们都列出了数据库中所有客户的列表。

例如

  • 视图1
  • 视图2
  • VIEW3
  • View4
  • View5
  • View6
  • View7

现在,每个视图都有可能在任何这些视图中包含相同的客户。

以下是我目前使用UNION将所有内容整合到1个结果集中的示例: -

SELECT
CustomerId,
Account,
Name,
Balance,
'View1' AS [View 1 List]
FROM View1
UNION
SELECT
CustomerId,
Account,
Name,
Balance,
'View2' AS [View 2 List]
FROM View2
UNION
SELECT
CustomerId,
Account,
Name,
Balance,
'View3' AS [View 3 List]
FROM View3
UNION
SELECT
CustomerId,
Account,
Name,
Balance,
'View4' AS [View 4 List]
FROM View4
UNION
SELECT
CustomerId,
Account,
Name,
Balance,
'View5' AS [View 5 List]
FROM View5
UNION
SELECT
CustomerId,
Account,
Name,
Balance,
'View6' AS [View 6 List]
FROM View6
UNION
SELECT
CustomerId,
Account,
Name,
Balance,
'View7' AS [View 7 List]
FROM View7

此查询有2个问题。

1。我想排除第一个视图中的客户出现在其余视图中,然后继续从那里开始。因此,View 2中的客户不应包含来自View 1的任何客户。如果他们已经在View 1和2中,则view 3将不会有任何客户。如果他们已经在View 4中,那么它将不会有任何客户查看1,2和3等:这将持续到第7个视图(视图7将不会在视图1,2,3,4,5和6中报告任何客户)

2。此当前查询最后会生成一列标题为“查看1列表”的列。然后识别客户所在的列表。

我正在寻找的是为每个View创建一个列的方法,该列将标识它们与哪个视图相关。该值可以是X或其他值。

不确定这是否可行,但是我知道我不能使用UNION语句。

2 个答案:

答案 0 :(得分:2)

默认情况下,

UNION实际上会删除重复项,因此,如果View 2中的客户在所有列中与View 1中的客户匹配,则无需执行任何操作。

更新:正如@Diego在下面指出的那样,我原来的解决方案将消除这一优势,因为为视图提供一列或多列将消除重复。一种解决方案是首先将UNION作为CTE,使用UNION来删除重复项,然后 找出它们来自的视图。

WITH UnionCTE AS
(
  SELECT
  CustomerId,
  Account,
  Name,
  Balance
  FROM View1

  UNION

  SELECT
  CustomerId,
  Account,
  Name,
  Balance
  From View2

  UNION
  ...
)
SELECT UnionCTE.*,
  CASE
    WHEN EXISTS (SELECT * FROM View1 WHERE CustomerId = UnionCTE.CustomerID) THEN 'View1'
    WHEN EXISTS (SELECT * FROM View2 WHERE CustomerId = UnionCTE.CustomerID) THEN 'View2'
    WHEN EXISTS (SELECT * FROM View3 WHERE CustomerId = UnionCTE.CustomerID) THEN 'View3'
    WHEN EXISTS (SELECT * FROM View4 WHERE CustomerId = UnionCTE.CustomerID) THEN 'View4'
    WHEN EXISTS (SELECT * FROM View5 WHERE CustomerId = UnionCTE.CustomerID) THEN 'View5'
    WHEN EXISTS (SELECT * FROM View6 WHERE CustomerId = UnionCTE.CustomerID) THEN 'View6'
    WHEN EXISTS (SELECT * FROM View7 WHERE CustomerId = UnionCTE.CustomerID) THEN 'View7'
  END AS [ViewNumber]
FROM UnionCTE

上面将创建一个列,显示数据的来源。如果您希望每个视图都有一个单独的列,则可以在CTE之后使用以下内容:

SELECT UnionCTE.*,
  CASE
    WHEN EXISTS (SELECT * FROM View1 WHERE CustomerId = UnionCTE.CustomerID) THEN 'X' 
    END AS [View1],
  CASE
    WHEN EXISTS (SELECT * FROM View2 WHERE CustomerId = UnionCTE.CustomerID) THEN 'X'
    END AS [View2],
    ...
  CASE
    WHEN EXISTS (SELECT * FROM View7 WHERE CustomerId = UnionCTE.CustomerID) THEN 'X'
    END AS [View7]
FROM UnionCTE

答案 1 :(得分:0)

CTE,UNION ALL和RANK()排名功能

的另一个选项
 ;WITH cte AS
 (
  SELECT CustomerId, Account, Name, Balance, 'View1' AS [ViewList]
  FROM View1
  UNION ALL
  SELECT CustomerId, Account, Name, Balance, 'View2'
  FROM View2
  UNION ALL
  SELECT CustomerId, Account, Name, Balance, 'View3'
  FROM View3
  UNION ALL
  SELECT CustomerId, Account, Name, Balance, 'View4'
  FROM View4
  UNION ALL
  SELECT CustomerId, Account, Name, Balance, 'View5'
  FROM View5
  UNION ALL
  SELECT CustomerId, Account, Name, Balance, 'View6'
  FROM View6
  UNION ALL
  SELECT CustomerId, Account, Name, Balance, 'View7'
  FROM View7
  ), cte2 AS
 (
  SELECT *, RANK() OVER(PARTITION BY CustomerId ORDER BY [ViewList] ASC) AS rn
  FROM cte  
  )
  SELECT *
  FROM cte2
  WHERE rn = 1

SQLFiddle

上的简单示例