-1

Let's say I have a table with 3 columns; people's salaries, how much they spend in a year, and their credit score.

Next, let's say I want to flag people with low salaries, who spend most of what they earn, and who also have bad credit scores. When doing some analytics on it, I may have to say something like

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

It's possible that I may have to reference those three conditions multiple times throughout a query. Can I just create a boolean that'll encompass all three of those?

For example

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

So the aim of the boolean is to shorten that three-condition statement into one variable and then the variable is referenced instead of the three statements. And every time it checks a row of data, it computes @flag and acts upon the result.

Greg G
  • 1
  • 3
  • 1
    There is no such thing as a `boolean` in `SQL Server`. The most common way to indicate a bool in `SQL Server` is to use a `bit` (`0`/`1`). – Siyual Jul 26 '16 at 14:47
  • user defined function? That would only apply if you wanted it to be a permanent part of the database. There's no temporary UDFs. – Damien_The_Unbeliever Jul 26 '16 at 14:49
  • sql server has a datatype called bit. It can only be 0 or 1 and languages like c# or delphi can recognize it as boolean. In sql server you will have to check like this if @flag = 1 then – GuidoG Jul 26 '16 at 14:50

3 Answers3

1

Sql server has no boolean data type available for users. You can use a Bit data type variable, that can hold 1, 0 or null values, like this:

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

In case this is meant to be used for multiple rows, you can do something like this:

;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
)

So now you have a bit column that's called SpentTooMuch that will hold the result of this calculation for every row in the table.

Zohar Peled
  • 79,642
  • 10
  • 69
  • 121
0

You should look into using a CTE, this will let you define this flag once, then you can use a join or apply to use this later on in your query.

Here are some useful references on CTEs;

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/

You can do something like (obviously contrived example as I don't know your table structures and surrounding context but hopefully puts you on right path);

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
Milney
  • 6,253
  • 2
  • 19
  • 33
  • not my downvote, i like the idea but why do you join yourtable with yourtable? – A ツ Jul 26 '16 at 14:58
  • Thank you for the reply. At a few points in my query, I do use CTEs when I need to update some Lag/Lead values since they are window functions. My only concern is the size of my table might make staging new information and joining take a while, but I'll keep this in mind. – Greg G Jul 26 '16 at 15:06
  • Actually using functions is more likely to give you a bad plan than joins if you are concerned about performance... Please read up on this. I will try add a link later but am too busy currently – Milney Jul 26 '16 at 15:12
0

Create a function and call it in your query.

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

You can call it like this

 DELETE FROM [dbo].[MyTable] WHERE [dbo].GetMyFlag (salary, spent, credit_socre) = 1
Marko Juvančič
  • 5,792
  • 1
  • 25
  • 41
  • Thank you for the reply. How would I call this function? If I wanted to drop the records of those who meet the three conditions, would I say DELETE FROM [dbo].[MyTable] WHERE [dbo].[GetMyFlag] = 1? – Greg G Jul 26 '16 at 15:10