【问题标题】:How to create a boolean in SQL that is checked every time I call it如何在 SQL 中创建一个布尔值,每次调用它时都会检查它
【发布时间】:2016-07-26 14:47:02
【问题描述】:

假设我有一个包含 3 列的表格;人们的薪水、他们一年的花费以及他们的信用评分。

接下来,假设我要标记低薪、大部分收入都花在了他们身上,并且信用评分也很差的人。在对其进行一些分析时,我可能不得不说类似

when(
    salary < 40000
     and
    spent > 0.75*salary
     and
    credit_score < 500
) then do_something

我可能必须在整个查询中多次引用这三个条件。我可以创建一个包含所有这三个的布尔值吗?

例如

Declare @flag boolean  
@flag = case
    when(
        salary < 40000
         and
        spent > 0.75*salary
         and
        credit_score < 500
    ) then true
    else false

/* Then later on in the program */

    when(
    @flag
    ) then do_something

所以布尔值的目的是将三条件语句缩短为一个变量,然后引用该变量而不是三个语句。每次检查一行数据时,它都会计算@flag 并根据结果进行操作。

【问题讨论】:

  • SQL Server 中没有 boolean 这样的东西。在SQL Server 中表示布尔值的最常见方法是使用bit (0/1)。
  • 用户定义函数?仅当您希望它成为数据库的永久部分时才适用。没有临时 UDF。
  • sql server 有一个数据类型叫做 bit。它只能是 0 或 1,像 c# 或 delphi 这样的语言可以将其识别为布尔值。在 sql server 中,如果 @flag = 1 then,你必须像这样检查

标签: sql-server tsql boolean declare


【解决方案1】:

Sql 服务器没有可供用户使用的布尔数据类型。您可以使用 Bit 数据类型变量,它可以保存 10null 值,如下所示:

Declare @flag bit
@flag = case
    when(
        salary < 40000
         and
        spent > 0.75*salary
         and
        credit_score < 600
    ) then 1
    else 0 end

/* Then later on in the program */

    when @flag = 1 then 
    -- do_something
    end

如果这意味着用于多行,您可以执行以下操作:

;WITH cte as
(
    SELECT  salary, 
            spent, 
            credit_score, 
            CAST(
                CASE WHEN  salary < 40000
                    AND spent > 0.75*salary
                    AND  credit_score < 600
                THEN 1
                ELSE 0 END
            As Bit) As SpentTooMuch
    FROM TableName
)

所以现在您有一个名为 SpentTooMuch 的位列,它将保存表中每一行的计算结果。

【讨论】:

  • 当然不是,但是问题中的什么暗示它应该是多行的结果?我在这里错过了什么吗?
  • 因为他用复数形式说“标记人”?
  • @Milney:我明白你的意思。编辑了我的答案并为你的答案投票。
  • 感谢您的回复。当我说“标记人们”时,我会澄清一下。我只打算逐案查看个人,没有人会影响其他人的结果。
  • 好吧,在这种情况下,一个简单的位类型标量变量就足够了。
【解决方案2】:

您应该考虑使用 CTE,这将让您定义此标志一次,然后您可以使用连接或申请稍后在您的查询中使用它。

这里有一些关于 CTE 的有用参考资料;

https://technet.microsoft.com/en-us/library/ms190766(v=sql.105).aspx

https://www.simple-talk.com/sql/t-sql-programming/sql-server-cte-basics/

你可以这样做(显然是人为的例子,因为我不知道你的表格结构和周围的上下文,但希望你能走上正确的道路);

WITH FlagCTE AS (
SELECT 
    PersonId,
    CASE WHEN salary < 40000
          and spent > 0.75*salary
          and credit_score < 500 then 1 else 0 end AS BadFlag
FROM YourTable
)
SELECT 
    PersonId,
    CASE WHEN BadFlag = 1 AND SomethingElse THEN 10 ELSE 0 END AS OtherColumn
FROM YourTable tab
LEFT OUTER JOIN FlagCTE flag
    on tab.PersonId = flag.PersonId

【讨论】:

  • 不是我的反对意见,我喜欢这个主意,但你为什么要加入 yourtable 和 yourtable?
  • 感谢您的回复。在我的查询中的几个点,当我需要更新一些滞后/领先值时,我确实使用 CTE,因为它们是窗口函数。我唯一担心的是我的桌子的大小可能会使暂存新信息和加入需要一段时间,但我会记住这一点。
  • 如果您担心性能,实际上使用函数比连接更有可能给您一个糟糕的计划...请阅读此内容。我稍后会尝试添加链接,但目前太忙了
【解决方案3】:

创建一个函数并在您的查询中调用它。

ALTER FUNCTION [dbo].[GetMyFlag]
(
   @Salary decimal(18,2),
   @Spent decimal(18,2),
   @CreditScore int
)
RETURNS bit
AS
BEGIN
    IF @Salary < 40000 AND @Spent > 0.75*@Salary AND @CreditScore < 600
       RETURN 1

    RETURN 0
END

你可以这样称呼它

 DELETE FROM [dbo].[MyTable] WHERE [dbo].GetMyFlag (salary, spent, credit_socre) = 1

【讨论】:

  • 感谢您的回复。我该如何调用这个函数?如果我想删除满足三个条件的人的记录,我会说DELETE FROM [dbo].[MyTable] WHERE [dbo].[GetMyFlag] = 1?
猜你喜欢
  • 2018-04-12
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 2019-04-27
  • 1970-01-01
  • 2016-01-04
  • 1970-01-01
  • 2017-07-20
相关资源
最近更新 更多