【问题标题】:Returning rows where various combinations of nulls may exist返回可能存在各种空值组合的行
【发布时间】:2015-08-03 16:13:43
【问题描述】:

我正在寻找将满足各种标准的记录提取为一个结果集的最佳方法。我正在使用 SQL Azure。

在一个稍微简化的示例中,这是我的场景(我附上了这部分架构的图表以帮助澄清!):

我在 tblCourseStudents 中有学生出勤记录。一列是 SponsorID - 这是为课程“赞助”该人的人的 ID - 通常但不总是,他们的经理。这是一个外键,与 tblPeople 中的 PersonID 相关。但是,在许多情况下,此列是空的,因为该公司历来并不总是记录该信息。

在 tblPeople 中,有一个 CompanyID 列,用于标识任何人为哪个公司工作。还有一个名为 IsPrimary (BIT) 的列,对于被确定为该公司主要联系人的人员,该列将设置为 1。公司里可能没有人担任初级职务,但这样的人永远不会超过一个。

我想运行一个显示以下内容的查询:

  1. 学生详细信息,包括
  2. 赞助商的姓名和电子邮件,如果赞助商 ID 不为空(如 “赞助商”),或者如果这是 null
  3. 此人的姓名和电子邮件地址 学生所在的公司标记为 IsPrimary = True,其中 人存在,或者
  4. “赞助商”的学生详细信息为 NULL 以上都不存在的细节。

有人可以帮忙吗?我已经盯着屏幕看够久了。

这是该架构:

【问题讨论】:

  • 这看起来很像家庭作业。你试过什么?
  • 我受宠若惊! 25年没做作业了!!!我一直在研究使用 CASE WHEN SponsorID IS NULL THEN tblPeople.PersonID 的想法 - 但无法弄清楚指定附加检查的方式,以便 WHEN 子句仅返回它们相同的 PersonID公司,它们设置为 IsPrimary=1。我还考虑使用一个视图,该视图将返回一个列中所有人的 ID(以显示赞助商)和另一个列中的主要联系人的 ID,并在连接中使用 ISNULL(),但我读到这是非常低效的(我可以想象。
  • 无论您的年龄多大……您还没有回答他最重要的问题吗? “你试过什么?”
  • 我试图解释我的尝试,但没有意识到按 Enter 不会插入换行符,但会发布我的回复......方格纸是顺便说一句,这不是家庭作业书的标志(这些东西还存在吗?),而是我在平板电脑上使用 Papyrus,就像我在所有数据库设计中一样!
  • 当然,方格纸和表格名称的组合使它看起来像家庭作业。此外,tbl 前缀是我们在家庭作业中经常看到的,而在现实世界中却很少见。

标签: sql-server tsql azure


【解决方案1】:

应该这样做,不需要 CASE 语句。

SELECT stud.Name, stud.Email,
     coalesce(sponsor.Name,'') SponsorName, coalesce(sponsor.Email,'') SponsorEmail
FROM tblCourseStudents cs
INNER JOIN tblPeople stud on stud.ID = cs.StudentID
LEFT JOIN tblPeople prime ON prime.CompanyID = stud.CompanyID AND prime.IsPrimary = 1
LEFT JOIN tblPeople sponsor on sponsor.ID = COALESCE(cs.SponsorID, prime.ID)

您可以进一步改进这一点,用一个 APPLY 运算符替换 tblPeople 的两个 JOIN。

【讨论】:

  • 非常感谢您在这方面的帮助 - 这太棒了。
【解决方案2】:

请试试这个查询:

select 
S.*,
CASE 
    WHEN Sponsor.PersonID is not null or (Sponsor.PersonID is null and Contact.PersonID is null) 
    THEN Sponsor.fname +' '+Sponsor.lname ELSE Contact.fname +' '+Contact.lname 
END as Name,
CASE 
    WHEN Sponsor.PersonID is not null or (Sponsor.PersonID is null and Contact.PersonID is null) 
    THEN Sponsor.email ELSE Contact.email 
END as Email

from tblCourseStudents S 
    left join tblPeople Sponsor 
         on Sponsor.personID=S.SponsorID 
    left join tblPeople StudentCompany 
         on StudentCompany.personID=S.StudentID 
    left join tblPeople Contact 
         on Contact.CompanyID=StudentCompany.CompanyID 
         and Contact.IsPrimary=1

【讨论】:

  • 太好了 - 感谢您的回答......现在就尝试一下(我必须做一些调整,因为我在某种程度上简化了发布的结构)并且会让你知道我的进展。再次感谢。
猜你喜欢
  • 2023-03-22
  • 2018-07-29
  • 1970-01-01
  • 2013-11-16
  • 2020-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-16
相关资源
最近更新 更多