2

如果表包含某种类型的记录,我如何为具有表记录子集、表的所有列以及其值设置为“X”的附加“标志”列的表创建视图?例如,考虑以下关系表Relations,其中类型的值代表H'-human, 'D'-dog

 id | type | relation | related
--------------------------------
 H1 |  H   | knows    | D2 
 H1 |  H   | owns     | D2 
 H2 |  H   | knows    | D1 
 H2 |  H   | owns     | D1
 H3 |  H   | knows    | D1
 H3 |  H   | knows    | D2
 H3 |  H   | treats   | D1
 H3 |  H   | treats   | D2
 D1 |  D   | bites    | H3
 D2 |  D   | bites    | H3

此表中可能没有任何特定的记录顺序。

我试图创建一个视图,该视图Humans将包含knows来自Relations和所有列的所有人与人之间的关系,以及如果给定关系中的人拥有某人的Relations附加列isOwner存储:'X'

 id | type | relation | related | isOwner
------------------------------------------
 H1 |  H   | knows    |    D2   |    X
 H2 |  H   | knows    |    D1   |    X
 H3 |  H   | knows    |    D1   |    

但为此苦苦挣扎。您是否知道一种方法来做到这一点,最好是一次CREATE VIEW通话,或者真的有什么方法?

4

3 回答 3

3
CREATE VIEW vHumanDogRelations
AS
SELECT
    id,
    type,
    relation,
    related,
    -- Consider using a bit 0/1 instead
    CASE 
        WHEN EXISTS (
            SELECT 1
            FROM Relations
            WHERE 
                id = r.id
                AND related = r.related -- Owns someone or this related only?
                AND relation = 'owns'    
        ) THEN 'X'
        ELSE ''
    END AS isOwner
FROM Relations r
WHERE 
    relation = 'knows'
    AND type = 'H'
    AND related = 'D';
于 2013-11-10T17:57:20.623 回答
2

您应该能够将以下内容select放入视图定义中

select *, case when exists 
(select * from Relations where id = r.id and relation= 'owns') then 'X'
else '' end as isOwner 
from Relations r
于 2013-11-10T17:58:53.017 回答
1

您还可以使用 PIVOT 来实现所需的结果。我将详细解释该方法,因为最终查询可能看起来令人困惑。

Relation首先,从where typeis Hanrelation或派生一个子集knowsownsowns值替换为X

SELECT
  id,
  type,
  relation = CASE relation WHEN 'owns' THEN 'X' ELSE relation END,
  related
FROM Relations
WHERE type = 'H'
  AND relation IN ('knows', 'owns')

根据您的示例,您将获得以下信息:

id  type  relation  related
--  ----  --------  -------
H1   H    knows     D2
H1   H    owns      D2
H2   H    knows     D1
H2   H    owns      D1
H3   H    knows     D1
H3   H    knows     D2

接下来,将此 PIVOT 子句应用于第一个查询的结果:

PIVOT (
  MAX(relation) FOR relation IN (knows, X)
) AS p

它将具有相同id, type, related值的行分组为一行并分成relation两列,knows并且X

id  type  related  knows  X
--  ----  -------  -----  ----
H1   H    D2       knows  X
H2   H    D1       knows  X
H3   H    D1       knows  NULL
H3   H    D2       knows  NULL

此时,您只需为主 SELECT 子句中的输出稍微重新排列列集,并在此过程中重命名knowsrelationXto isOwner

SELECT
  id,
  type,
  relation = knows,
  related,
  isOwner = X
...

输出:

id  type  relation  related  isOwner
--  ----  --------  -------  -------
H1   H    knows     D2       X
H2   H    knows     D1       X
H3   H    knows     D1       NULL
H3   H    knows     D2       NULL

当然,如果有必要,NULL 可以很容易地用空字符串替换。

最后一步可能是将这个额外的过滤器添加到主查询中:

WHERE knows IS NOT NULL

以防万一有人在实际上不认识狗的情况下拥有狗(并且您不希望输出中出现这些狗)。

因此,完整的查询将如下所示:

SELECT
  id,
  type,
  relation = knows,
  related,
  isOwner = X
FROM (
  SELECT
    id,
    type,
    relation = CASE relation WHEN 'owns' THEN 'X' ELSE relation END,
    related
  FROM Relations
  WHERE type = 'H'
    AND relation IN ('knows', 'owns')
) AS s
PIVOT (
  MAX(relation) FOR relation IN (knows, X)
) AS p
WHERE knows IS NOT NULL
;

此解决方案的 SQL Fiddle 演示可在此处获得。

于 2013-11-13T00:05:43.323 回答