【问题标题】:Case statement returning a select where query返回 select where 查询的 case 语句
【发布时间】:2014-10-27 11:14:34
【问题描述】:

我对此选择查询的逻辑有问题。

SELECT

ISNULL((SELECT cs_facilities.name from cs_facilities where ci_periodicBillings.facility = cs_facilities.guid),'Unknown') as [Care Centre],

ISNULL((SELECT cs_clients.title + ' ' + cs_clients.forename + ' ' + cs_clients.surname from cs_clients where ci_periodicBillings.client = cs_clients.guid),'Unknown') as [Resident Name],

***CASE WHEN ci_periodicbillings.contributionFunder = '00000000-0000-0000-0000-000000000000' then 'No Funder' ELSE (select ci_contributionFunders.name from ci_contributionFunders where ci_contributionFunders.guid = ci_periodicBillings.contributionFunder) END as [Contribution Funder],***

ISNULL((SELECT cs_clients.ADMISSION from cs_clients where ci_periodicBillings.client = cs_clients.guid),'') as [Admission Date],

ISNULL(ci_periodicbillings.RATE,'') as [Weekly Rate],

CASE WHEN BILLRES = 1 THEN 'Self Payer' ELSE CASE WHEN BILLRES = 2 THEN 'Top up' ELSE 'Other Funder' END END as [Type of Funding],

ISNULL(ci_periodicbillings.LASTBILL,'') as [Billing Period Start Date],

ISNULL(ci_periodicbillings.NEXTBILL,'') as [Billing Period Next Repeat Date],

CASE WHEN invoiceDaysOffset = 22 then 'In Arrears' ELSE CASE WHEN invoicedaysoffset = -6 then 'In Advance' ELSE '' END END as [Advance or Arrears Billing]


from ci_periodicBillings
where facility = '00000000-0000-0000-0000-000000000000'
and ENDBILL = '1900-01-01 00:00:00.000'
order by [Care Centre], [Resident Name]

我相信您的专家会发现有问题的线是用三颗星突出显示的线。

我希望你能在这里看到我的逻辑。在 ci_periodicbillings 表中有一个标记为“contributionFunder”的列。这指的是 ci_contributionFunders 表中的一个 guid。我希望我的案例陈述说明这是否为空 guid(即 '00000000-0000-0000-0000-000000000000')然后没有资助者,否则如果 guid 与 ci_periodicbillings 表中的列 guid 匹配,则返回 ci_contributionfunders .name 值,即资助者的名称。

谁能帮我整理一下?

【问题讨论】:

  • 你有什么问题?
  • 问题是基于星号段的查询失败,这是一个试图返回捐款资助者名称的案例语句
  • “查询失败”能否再清楚一点?错误信息是什么?
  • 嗨,Gareth - 显然我并没有想象中那么清醒,它只是构造不佳。在下面的答案中使用 case 语句,它现在可以正确返回。这是一个永远不会返回 NULL 值的列,因此不需要 ISNULL 子句。

标签: sql select case


【解决方案1】:

我不知道你的错误信息是什么,我也看不出你的查询有什么实际问题,但在整理它时,我会做一些事情。

第一个是删除所有相关的子查询,并使用LEFT JOIN 代替,第二个是使用表别名而不是在整个查询中重复完整的表名。最后,我会简化 case 语句而不是嵌套它们:

SELECT  ISNULL(f.Name, 'Unknown') AS [Care Centre],
        ISNULL(c.title + ' ' + c.forename + ' ' + c.surname, 'Unknown') AS [Resident Name],
        ISNULL(cf.Name, 'No Funder') AS [Contribution Funder],
        ISNULL(c.ADMISSION, '') AS [Admission Date],
        ISNULL(pb.RATE,'') AS [Weekly Rate],
        CASE pb.BILLRES
            WHEN 1 THEN 'Self Payer' 
            WHEN 2 THEN 'Top up' 
            ELSE 'Other Funder' 
        END AS [Type of Funding],
        ISNULL(pb.LASTBILL,'') AS [Billing Period Start Date],
        ISNULL(pb.NEXTBILL,'') AS [Billing Period Next Repeat Date],
        CASE pb.invoiceDaysOffset
            WHEN 22 THEN 'In Arrears' 
            WHEN -6 THEN 'In Advance' 
            ELSE ''
        END AS [Advance or Arrears Billing]
FROM    ci_periodicBillings AS pb
        LEFT JOIN cs_facilities AS f
            ON f.guid = pb.facility
        LEFT JOIN cs_clients AS c
            ON c.guid = pb.client
        LEFT JOIN ci_contributionFunders AS cf
            ON cf.guid = pb.contributionFunder
            AND pb.contributionFunder != '00000000-0000-0000-0000-000000000000'
WHERE   pb.facility = '00000000-0000-0000-0000-000000000000'
AND     pb.ENDBILL = '1900-01-01 00:00:00.000';

我会做的最后一件事是切换到 SQL Server 允许的 Alias = <Expression> 语法,而不是 <Expression> AS Alias,因此我故意将其分开,因为它非常主观。我发现这更清晰,因为您通过扫描选择列表立即看到您正在查看的列。 Aaron Bertrand 写了一封 good article,或多或少地反映了我对这个主题的感受。

SELECT  [Care Centre] = ISNULL(f.Name, 'Unknown'),
        [Resident Name] = ISNULL(c.title + ' ' + c.forename + ' ' + c.surname, 'Unknown'),
        [Contribution Funder] = ISNULL(cf.Name, 'No Funder'),
        [Admission Date] = ISNULL(c.ADMISSION, ''),
        [Weekly Rate] = ISNULL(pb.RATE,''),
        [Type of Funding] = CASE pb.BILLRES
                                WHEN 1 THEN 'Self Payer' 
                                WHEN 2 THEN 'Top up' 
                                ELSE 'Other Funder' 
                            END,
        [Billing Period Start Date] = ISNULL(pb.LASTBILL,''),
        [Billing Period Next Repeat Date] = ISNULL(pb.NEXTBILL,''),
        [Advance or Arrears Billing] = CASE pb.invoiceDaysOffset
                                            WHEN 22 THEN 'In Arrears' 
                                            WHEN -6 THEN 'In Advance' 
                                            ELSE ''
                                        END
FROM    ci_periodicBillings AS pb
        LEFT JOIN cs_facilities AS f
            ON f.guid = pb.facility
        LEFT JOIN cs_clients AS c
            ON c.guid = pb.client
        LEFT JOIN ci_contributionFunders AS cf
            ON cf.guid = pb.contributionFunder
            AND pb.contributionFunder != '00000000-0000-0000-0000-000000000000'
WHERE   pb.facility = '00000000-0000-0000-0000-000000000000'
AND     pb.ENDBILL = '1900-01-01 00:00:00.000';

【讨论】:

  • 嗨,Gareth - 这看起来比我的工作要干净得多,但是在切换到 JOIN 结构化查询时我遇到了一件困难的事情,那就是在最后添加多个 WHERE 子句。在我的原始查询中,我有大约 4 个 where 子句,包括 - where pb.ENDBILL = '01/01/1900' - 你能告诉我如何将这种灵活性融入你的格式吗?
  • 抱歉,不知道为什么我错过了他们。我刚刚将它们添加到答案中。 WHERE 的结构不受 JOIN 的影响。
  • 一个问题 - 我可以看到结果,但你能解释一下这个语法是如何工作的:LEFT JOIN ci_contributionFunders AS cf ON cf.guid = pb.contributionFunder AND pb.contributionFunder != '00000000-0000- 0000-0000-000000000000'
  • 这只是连接中的一个附加子句,表示我不想要来自 ci_contributionFunders 的任何行,其中 pb.contributionFunder = '000...' - 这样你就不需要做案例声明CASE WHEN pb.contributionFunder = '000...,你可以只使用ISNULL(cf.Name, 'unknown'),因为贡献资助者为0的任何行都不会返回cf.name的结果
  • 嗨,我现在正在尝试 Alias = Expression,进展顺利,不过有几个问题。 1 - SQL 中是否有正式采用此开关的设置,因为当我打开 [ 尝试引用列/表/数据库并自动填充的括号时,我一直遇到问题。我非常喜欢自动填充功能,所以如果可能的话,我想保留它。 2 - CASE 查询不能很好地处理数字 - 看看这不起作用:[销售分类帐交易类型] = CASE id.amount WHEN > 0.00 THEN 'Invoice' WHEN
【解决方案2】:

这是什么方言?

你使用case when ... then ... else case when ... then ...

但我知道的任何方言的正确语法是:

case when ... then ... when ... then ... else ... end

对于您的问题,我建议先离开加入,然后使用isnull 函数。

【讨论】:

  • 您好,我已更新以考虑您的语法 - CASE WHEN ci_periodicbillings.contributionFunder = '00000000-0000-0000-0000-000000000000' 然后 'No Funder' 当 ci_periodicbillings.contributionFunder '00000000- 0000-0000-0000-000000000000' THEN (select ci_contributionFunders.name from ci_contributionFunders.guid = ci_periodicBillings.contributionFunder) END as [Contribution Funder], - 这只是 SQL 管理工作室中的 Select 查询。它仍然返回一个错误,并且 (SELECT) 部分带有下划线。我不知道如何在这里表达 join/isnull ..
  • (1) 这更适合作为评论。 (2) 所有支持case语句的SQL版本都允许嵌套case语句。语法可能不正统,但它是正确的。
  • 我刚刚意识到我的查询写得不好并修复了它 - 很抱歉浪费了您的时间!
【解决方案3】:

使用您的语法,case 语句适用于:

CASE WHEN ci_periodicbillings.contributionFunder = '00000000-0000-0000-0000-000000000000' then 'No Funder' when ci_periodicbillings.contributionFunder <> '00000000-0000-0000-0000-000000000000' THEN (select ci_contributionFunders.name from ci_contributionFunders where ci_contributionFunders.guid = ci_periodicBillings.contributionFunder) END as [Contribution Funder],

【讨论】:

    猜你喜欢
    • 2013-03-23
    • 1970-01-01
    • 2022-01-17
    • 2014-10-13
    • 2011-11-01
    • 2013-07-19
    • 2019-05-01
    • 1970-01-01
    • 2017-09-17
    相关资源
    最近更新 更多