CASE中的SELECT语句

时间:2015-06-29 20:06:37

标签: sql sql-server sql-server-2008 tsql

请不要降级,因为我解释起来有点复杂。我正在进行数据迁移,所以有些结构看起来很奇怪,因为它是由那样的人设计的。

对于ex,我有一个表Person的PersonID和PersonName作为列。我在表格中有重复。

我有详细信息表,其中PersonName存储在列中。 PersonName可能存在于Person表中,也可能不存在。我需要从匹配的记录中检索PersonID,否则在PersonID中放入一些硬编码值。

我无法写下面的查询,因为PersonName在Person Table中重复,如果由于连接而存在匹配的记录,则此连接会使行加倍。

SELECT d.Fields, PersonID
FROM Details d
JOIN Person p ON d.PersonName = p.PersonName

以下查询有效,但我不知道如何替换" NULL"我需要一些值代替NULL

SELECT d.Fields, (SELECT TOP 1 PersonID FROM Person where PersonName = d.PersonName )
FROM Details d

因此,Details表中有一些PersonNames在Person表中不存在。在这种情况下如何编写CASE?

我在下面试过,但它没有工作

 SELECT d.Fields, 
       CASE WHEN (SELECT TOP 1 PersonID 
                 FROM Person 
                 WHERE PersonName = d.PersonName) = null 
       THEN 123 
       ELSE (SELECT TOP 1 PersonID 
              FROM Person 
              WHERE PersonName = d.PersonName) END Name
    FROM Details d

此查询仍显示与第二个查询相同的输出。请告诉我这个。如果我在任何地方都不清楚,请告诉我。感谢

4 个答案:

答案 0 :(得分:2)

嗯..我想我可以将ISNULL置于SELECT之上以使其正常工作。

SELECT d.Fields, 
    ISNULL(SELECT TOP 1 p.PersonID 
           FROM Person p where p.PersonName = d.PersonName, 124) id
    FROM Details d

答案 1 :(得分:1)

一个简单的左外连接可以在详细信息表上拉回所有具有可选匹配的人,应该使用case语句来获得所需的结果。

void log_function(t_log* logger, const char* message_template, ...);

答案 2 :(得分:0)

好的,好吧,有机会使用两个LEFT JOIN。第一个将列出它们存在的ID,否则插入默认值;第二个将消除重复。

   SELECT d.Fields, ISNULL(p1.PersonID, 123)
     FROM Details d
LEFT JOIN Person p1 ON d.PersonName = p1.PersonName
LEFT JOIN Person p2 ON p2.PersonName = p1.PersonName
                   AND p2.PersonID < p1.PersonID
    WHERE p2.PersonID IS NULL

答案 3 :(得分:0)

您可以使用公用表表达式来构建缺少的数据集,即完整的Person表,然后将其连接到Detail表,如下所示;

declare @n int;
-- set your default PersonID here;
set @n = 123;

-- Make sure previous SQL statement is terminated with semilcolon for with clause to parse successfully.

-- First build our unique list of names from table Detail.
with cteUniqueDetailPerson
(
    [PersonName]
)
as
(
    select distinct [PersonName]
    from [Details]
)

-- Second get unique Person entries and record the most recent PersonID value as the active Person.
, cteUniquePersonPerson
(
      [PersonID]
    , [PersonName]
)
as
(
    select
          max([PersonID]) -- if you wanted the original Person record instead of the last, change this to min.
        , [PersonName]
    from [Person]
    group by [PersonName]
)

-- Third join unique datasets to get the PersonID when there is a match, otherwise use our default id @n.
-- NB, this would also include records when a Person exists with no Detail rows (they are filtered out with the final inner join)
, cteSudoPerson
(
      [PersonID]
    , [PersonName]
)
as
(
    select
        coalesce(upp.[PersonID],@n) as [PersonID]
        coalesce(upp.[PersonName],udp.[PersonName]) as [PersonName]
    from cteUniquePersonPerson upp
    full outer join cteUniqueDetailPerson udp
        on udp.[PersonName] = p.[PersonName]
)

-- Fourth, join detail to the sudo person table that includes either the original ID or our default ID.
select
      d.[Fields]
    , sp.[PersonID]
from [Details] d
inner join cteSudoPerson sp
    on sp.[PersonName] = d.[PersonName];