2

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

例如。

  • 视图1
  • 视图2
  • 视图3
  • 查看4
  • 视图5
  • 视图6
  • 视图7

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

这是我目前使用 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.我想排除第一个视图中的客户出现在其余视图中,然后从那里继续上升。因此,视图 2 中的客户不应包含视图 1 中的任何客户。如果视图 3 已经在视图 1 和 2 中,则视图 3 将没有任何客户。如果视图 4 已经在视图 4 中,则不会有任何客户视图 1、2 和 3 等:这将持续到第 7 个视图(视图 7 不会在视图 1、2、3、4、5 和 6 中报告任何客户)

2.此当前查询在末尾生成一列,标题为“查看 1 列表”,然后标识客户所在的列表。

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

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

4

2 回答 2

2

UNION实际上默认情况下会删除重复项,因此如果视图 2 中的客户将在所有列中与视图 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
于 2013-03-01T13:09:46.853 回答
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上的简单示例

于 2013-03-01T14:22:44.287 回答