基于值的存在的表的条件连接

时间:2014-03-12 15:09:25

标签: sql sql-server-2008-r2

在我们的数据模型中有一个人。

一个人住在一所房子里。

一个人可以有一个'订阅'。 (这与订阅构成的内容无关)

众议院可以有一个'订阅'。

订阅具有SubscriptionNumber。

因此,这个数据模型允许Person直接订阅,也可以通过他们的House。

现在进行查询。

如果此人通过其众议院订阅,则与该订阅相关联的SubscriptionNumber需要以结果结束。如果不是这种情况,则与订阅直接相关的订阅关联的SubscriptionNumber需要以结果结束(如果不存在则为NULL)。

此查询的结果将显示在网格中。我们允许用户在此列上指定过滤和排序。这意味着一些事情:

1)    We cannot simply specify a CASE in the 'main' select statement and alias that result, 
      because this disallows us to filter on it, since WHERE is processed before SELECT. 
2)    For the filtering to be meaningful the result has to be 'put' in one alias 

我对数据库开发很陌生并完全陷入困境,但这是我到现在为止所提出的:

1)    Using a query like this:

      SELECT 
           (CASE 
               WHEN (House of person has subscription)
               THEN (return subscription number of house)
               ELSE (return subscription number of person)
            END) AS SubscriptionNumber
      This leaves me with the exception regarding the unknown column when i try to apply ordering   on SubscriptionNumber. Is there some way to avoid this?


2)    Joining the 2 tables in the FROM list:
      ...
      FROM People
      JOIN (...) AS HouseSubscriptionNumber
      JOIN (...) AS PersonSubscriptionNumber

      This leaves me with 2 seperate columns, which also disallows my ordering.

我在概念上寻找的是根据其存在提取任何一种方法。 我一直在摸索子查询和工会以及各种各样的东西,但我总是得到某种脑循环:-(例如,我可以写出类似的东西:

FROM People 
JOIN (
    SELECT 
        SubscriptionNumber = 
            CASE ...
            END)

但是我如何将其加入主查询?

很多问题! 有没有办法实现这个目标?

2 个答案:

答案 0 :(得分:8)

在示例中使用方法1的最简单方法是CROSS APPLY。使用CROSS APPLY子句处理FROM,其中的任何别名都可以像普通表中的列名一样重复使用:

SELECT 
...
CxA.SubscriptionNumber
FROM
    MyTables
CROSS APPLY
    (SELECT CASE 
        WHEN (House of person has subscription)
        THEN (return subscription number of house)
        ELSE (return subscription number of person)
    END) CxA(SubscriptionNumber)

在示例中CxA只是CROSS APPLY表达式的别名(就像表别名一样,使它成为你想要的任何东西),而SubscriptionNumber是列别名。

答案 1 :(得分:2)

由于我没有您的表定义,因此组成关系。 这样做,它将人员表连接到house表并找到订阅号(如果它存在,如果它不存在则返回null)。它还将通过personID转到订阅表并查找订阅(如果存在,如果它不存在也将返回null)

然后我们使用COALESCE来查找第一个非空数字。如果两个订阅都不存在,则返回-1

SELECT COALESCE (su.SubscriptionNumber,s.subscriptionNumber,-1) as Target
FROM Person AS p 
INNER JOIN house AS h ON p.houseid = h.houseid --assuming a person can only live in 1 house

LEFT JOIN Subscription AS s ON p.subscriptionNumber = s.SubscriptionNumber
LEFT JOIN Subscription AS su ON h.SubscriptionNubmer = su.SubscriptionNumber
ORDER BY target DESC

如果你想在where子句中

SELECT TARGET FROM (
    SELECT COALESCE (su.SubscriptionNumber,s.subscriptionNumber,-1) as Target
    FROM Person AS p 
    INNER JOIN house AS h ON p.houseid = h.houseid --assuming a person can only live in 1 house

    LEFT JOIN Subscription AS s ON p.subscriptionNumber = s.SubscriptionNumber
    LEFT JOIN Subscription AS su ON h.SubscriptionNubmer = su.SubscriptionNumber
) as mark
WHERE MARK.TARGET = XXXX