Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 assigning multiple values under one CASE

Author  Topic 

yosiasz
Master Smack Fu Yak Hacker

1635 Posts

Posted - 2010-03-29 : 14:47:35
Greetings

We have one table which has both parent records and child records. There are lots of fields that will differ from parent to child. In order to display the correct parent or child value I am using the following case statement. There must be a better way.

CASE
WHEN child.ProID = '' OR child.ProID IS NULL THEN child.field1
ELSE parent.field1
END AS field1
CASE
WHEN child.ProID = '' OR child.ProID IS NULL THEN child.field2
ELSE parent.field2
END AS field2,


I was hoping to avoid as many CASE statement as the fields that might be different from parent child. Is that possible, if so if you would be kind enough to fill me in.

Thanks


<><><><><><><><><><><><><><><><><><><><><><><><><>
If you don't have the passion to help people, you have no passion

DBA in the making
Aged Yak Warrior

638 Posts

Posted - 2010-03-29 : 15:15:16
If you could replace all the empty strings in the child record with NULL, then you could use:

COALESCE(child.field1, parent.field1),
COALESCE(child.field2, parent.field2)


Coalesce return the first non-null argument passed to it. If the child.fieldx is null, then it will return parent.fieldx.

However, if the child field contains an empty string, then it will return that. You could also use:

ISNULL(child.field1, parent.field1),
ISNULL(child.field2, parent.field2)

which would achieve the same thing. ISNULL Does basically the same thing, but only takes 2 parameters. It would probably be faster the COALESCE, but I'm just guessing there.

There are 10 types of people in the world, those that understand binary, and those that don't.
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2010-03-30 : 13:58:25
quote:
Originally posted by DBA in the making

If you could replace all the empty strings in the child record with NULL, then you could use:

COALESCE(child.field1, parent.field1),
COALESCE(child.field2, parent.field2)


Coalesce return the first non-null argument passed to it. If the child.fieldx is null, then it will return parent.fieldx.

However, if the child field contains an empty string, then it will return that. You could also use:

ISNULL(child.field1, parent.field1),
ISNULL(child.field2, parent.field2)

which would achieve the same thing. ISNULL Does basically the same thing, but only takes 2 parameters. It would probably be faster the COALESCE, but I'm just guessing there.

There are 10 types of people in the world, those that understand binary, and those that don't.


The above solution doesnt make sense.
OP's post was showing conditional selection of child/parent fields based on third field child.ProID.
How can COALESCE or ISNULL used as above be an alternate for that? as per above suggestion it just takes first NOT NULL value out of child.field1 & parent.field1 but here third field child.ProID is not even in the frame which is not OP's scenario (at least as per initial post)

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page

DBA in the making
Aged Yak Warrior

638 Posts

Posted - 2010-03-30 : 14:09:29
I appear to have misread the opening post.

There are 10 types of people in the world, those that understand binary, and those that don't.
Go to Top of Page

PackRat
Starting Member

26 Posts

Posted - 2010-03-30 : 17:44:12
I believe I understand where you're trying to end up on this one; my appologies if not.

spent a bit more time on this than I ought to have, I've certainly been down this road before and most often ended up at some alternative revision or gone ahead with the case statement.

followed it through to its conclusion this time and before I present a the solution, which is not perfect, I'd pre-emtively recomend going with the case statement for legibility or some other alternative to the code I present below.

I didn't have a lot to go on for testing so I whipped up a test scenario, probably isn't an exact model but ought to be close enough to illustrate the solution and the inherent problems with it.

to summarize; you can get to a solution using ISNULL and NULLIF (i'll spare you the gory details), but the solution breaks if the data in the child fields contains empty strings or nulls. Not to mention it is ugly as sin.


DECLARE @parent TABLE(
PK TINYINT
, field1 VARCHAR(100)
, field2 VARCHAR(100)
);
INSERT @parent SELECT 0,'pf1','pf2';

DECLARE @child TABLE(
FK TINYINT
, IX TINYINT NOT NULL PRIMARY KEY
, ProID VARCHAR(100)
, field1 VARCHAR(100)
, field2 VARCHAR(100)
);
INSERT @child
SELECT 0, 1, 'A' ,'cf1' ,'cf2' UNION ALL -- test 1
SELECT 0, 2, 'B' ,'cf1' ,'cf2' UNION ALL -- test 2
SELECT 0, 3, '' ,'cf1' ,'cf2' UNION ALL -- test 3
SELECT 0, 4, NULL ,'cf1' ,'cf2' UNION ALL -- test 4
SELECT 0, 5, '' ,'' ,NULL UNION ALL -- control 1; ProID is an empty string,
--child fields should come through as empty/null, but will be replaced by parent fields instead
SELECT 0, 6, NULL ,NULL ,'' UNION ALL -- control 2; ProID is null,
--child fields should come through as empty/null, but the null value in child field 1 will be replaced by the parent field
SELECT 0, 7, 'C' ,'' ,NULL UNION ALL -- control 3; works as advertized
SELECT 0, 8, 'D' ,NULL ,'' -- control 4; works as advertized
SELECT
[IX] =child.ix
,[ProID] =child.ProID
,[field1] =ISNULL(NULLIF(ISNULL(NULLIF(ISNULL(child.ProID, ''), ''), child.field1), child.ProID), parent.field1)
,[field2] =ISNULL(NULLIF(ISNULL(NULLIF(ISNULL(child.ProID, ''), ''), child.field2), child.ProID), parent.field2)
FROM @parent parent JOIN @child child ON parent.PK=child.FK;


result:

IX ProID F1 F2
1 A pf1 pf2 -- correct
2 B pf1 pf2 -- correct
3 cf1 cf2 -- correct
4 NULL cf1 cf2 -- correct
5 pf1 pf2 -- F1 should be NULL, F2 should be ''
6 NULL pf1 -- F1 should be '', F2 is correct
7 C pf1 pf2 -- correct
8 D pf1 pf2 -- correct


my only other recomendation is that you could try and abbreviate the case statement a bit and make it more legible:

,CASE ISNULL(child.ProID, '') WHEN '' THEN child.field1 ELSE parent.field1 END AS field1
,CASE ISNULL(child.ProID, '') WHEN '' THEN child.field2 ELSE parent.field2 END AS field2


lot easier to read and infalible with regards to the bug in the first block



wrote this on my TRS-80 COCO
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2010-03-30 : 23:38:21
I edited PackRat's post just to add two hard returns in there for display purposes in this forum. Two of his comments in the code continue on another line, so I added -- to the beginning to make it clear. Hope this helps.

Tara Kizer
Microsoft MVP for Windows Server System - SQL Server
http://weblogs.sqlteam.com/tarad/

Subscribe to my blog
Go to Top of Page

DonAtWork
Master Smack Fu Yak Hacker

2167 Posts

Posted - 2010-03-31 : 12:05:29

quote:
Originally posted by yosiasz

Greetings

We have one table which has both parent records and child records.


quote:
Originally posted by PackRat

I believe I understand where you're trying to end up on this one; my appologies if not.

[code]
DECLARE @parent TABLE(
PK TINYINT
, field1 VARCHAR(100)
, field2 VARCHAR(100)
);
INSERT @parent SELECT 0,'pf1','pf2';

DECLARE @child TABLE(
FK TINYINT
, IX TINYINT NOT NULL PRIMARY KEY
, ProID VARCHAR(100)
, field1 VARCHAR(100)
, field2 VARCHAR(100)
);




Your solution shows 2 tables, where his original problem has ONE table. Perhaps the OP can follow the HOW TO ASK link in my signature, and provide some DDL and sample data and output?

http://weblogs.sqlteam.com/jeffs/archive/2008/05/13/question-needed-not-answer.aspx
How to ask: http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx

For ultra basic questions, follow these links.
http://www.sql-tutorial.net/
http://www.firstsql.com/tutor.htm
http://www.w3schools.com/sql/default.asp
Go to Top of Page

PackRat
Starting Member

26 Posts

Posted - 2010-03-31 : 12:46:22
looked to me that the original had two table references; parent and child

parent.field1
child.field1

I made that inference since the dot notation wasn't encapulated by brackets:
[parent.field1]
[child.field1]

thought the author might have meant 'one query' rather than 'one table'. ... or maybe its a table joined on itself, mysteries abound.


_____________________________
wrote this on my TRS-80 COCO4

<PakRat/>
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2010-03-31 : 13:27:08
it does seem like he meant one query seeing the multiple aliases

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page

yosiasz
Master Smack Fu Yak Hacker

1635 Posts

Posted - 2010-04-12 : 14:46:56
sorry folks !! been away but issue is still around so here is some DDL. it is one table, with parent and child rows in same table




create table parent(project int, ref int, field1 varchar(12), field2 int, amount money)
--'parent row'
INSERT INTO [dbo].[parent]
([project]
,[ref]
,[field1]
,[field2]
,[amount])
VALUES
(1
,222
,'Credit'
,12354
,50)
----'child rows' in same table
INSERT INTO [dbo].[parent]
([project]
,[ref]
,[field1]
,[field2]
,[amount])
VALUES
(NULL
,222
,'Credit'
,12354
,50)


INSERT INTO [dbo].[parent]
([project]
,[ref]
,[field1]
,[field2]
,[amount])
VALUES
(NULL
,222
,'Credit'
,12354
,56789)


<><><><><><><><><><><><><><><><><><><><><><><><><>
If you don't have the passion to help people, you have no passion
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2010-04-12 : 14:58:37
so what should be your output?

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page
   

- Advertisement -