简体   繁体   中英

How do I make a boolean calculated field in TSQL and join on that calculated field?

First check out this code. I seems like it should work for me, but it doesn't! (surprise!)

Anyway, this is what I tried first:

SELECT
Status as status,
Address as ip,
PCName as pc_name,
(Numbers.Phone = 'CPU/' + PCName) as cpu_contact,
(Numbers.Phone = 'PC/' + PCName) as pc_contact,
(Numbers.Phone = 'LOGIN/' + PCName) as login_contact,
FROM IPAddress
WHERE $where  --Generated In code
JOIN Numbers
  ON ('CPU/' + PCName = Numbers.Phone) 
  OR ('PC/' + PCName = Numbers.Phone) 
  OR ('LOGIN/' + PCName = Numbers.Phone)

So what I want is some boolean calculated fields and to join on similar conditions. I would also like the result to collapse down to single rows. For example, I think the current setup would do something like this:

status ip  cpu_contact pc_contact login_contact
-----------------------------------------------
foo    bar true        false      false
foo    bar false       true       false
foo    bar false       false      true

And obviously I'd rather

status ip  cpu_contact pc_contact login_contact
-----------------------------------------------
foo    bar true        true       true

Any ideas? Database redesign isn't an option. If it were, I'd do that :-)

You could use a GROUP BY and SUM to collapse the rows:

SELECT
  Status as status, Address as ip, PCName as pc_name,
  cast(sum(case when (Numbers.Phone = 'CPU/' + PCName) then 1 else 0 end) as bit)
    as cpu_contact,
  cast(sum(case when (Numbers.Phone = 'PC/' + PCName) then 1 else 0 end)) as bit)
    as pc_contact,
  cast(sum(case when (Numbers.Phone = 'LOGIN/' + PCName) then 1 else 0 end) as bit)
    as login_contact,
FROM
  IPAddress
    JOIN Numbers ON 
      ('CPU/' + PCName = Numbers.Phone) OR ('PC/' + PCName = Numbers.Phone) OR 
      ('LOGIN/' + PCName = Numbers.Phone)
WHERE
  $where  --Generated In code
GROUP BY
  Status, Address, PCName

Since you are doing a logical or between the rows, a sum of zero is false, while any value greater than 0 will be true.

You need to use Case/When for the comparisons. In this case, I am hardcoding a 1 or 0, but T-SQL will convert the hard coded numbers to int. If you want boolean (bit), you'll need to convert that manually, like this...

Convert(Bit, Case When Numbers.Phone = 'CPU/' + PCName Then 1 Else 0 End) as cpu_contact,
Convert(Bit, Case When Numbers.Phone = 'PC/' + PCName Then 1 Else 0 End) as pc_contact,
Convert(Bit, Case When Numbers.Phone = 'LOGIN/' + PCName Then 1 Else 0 End) as login_contact,
SELECT
Status as status,
Address as ip,
PCName as pc_name,
case when sum(case when Numbers.Phone = 'CPU/' + PCName then 1 end) > 0 then 'true' else 'false' end as cpu_contact,
case when sum(case when Numbers.Phone = 'PC/' + PCName then 1 end) > 0 then 'true' else 'false' end as pc_contact,
case when sum(case when Numbers.Phone = 'LOGIN/' + PCName then 1 end) > 0 then 'true' else 'false' end as login_contact
FROM IPAddress
JOIN Numbers
  ON ('CPU/' + PCName = Numbers.Phone) 
  OR ('PC/' + PCName = Numbers.Phone) 
  OR ('LOGIN/' + PCName = Numbers.Phone)
WHERE -- your condition goes here
group by status, address, pc_name   

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM