如果同一表中存在某个记录,则设置列值

时间:2013-11-10 17:50:40

标签: sql sql-server

如何创建表的视图,其中包含表记录的子集,所有表的列,以及附加的“flag”列,如果表包含特定类型的记录,则其值设置为“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电话中,还是以任何方式?

3 个答案:

答案 0 :(得分: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';

答案 1 :(得分: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

答案 2 :(得分:1)

您还可以使用PIVOT来获得所需的结果。我会详细解释这个方法,因为最终的查询可能会让人感到困惑。

首先,从Relation派生一个子集,其中typeHrelation knowsowns,替换{{1} } owns的值:

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')

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

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 ( MAX(relation) FOR relation IN (knows, X) ) AS p 值的行分组到一行,并将id, type, related拆分为两列,relationknows

X

此时,您只需要为主SELECT子句中的输出稍微重新排列列集,将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 重命名为knows并将relation重命名为X沿着方式:

isOwner

输出:

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

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

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

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

以防有人在没有实际知道的情况下拥有狗(并且你不想在输出中使用它们)。

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

WHERE knows IS NOT NULL

此解决方案的SQL小提琴演示可用here