question

red68 avatar image
red68 asked

Checking column for value

Household may have 1 or more records. There is a customer type with value P for primary or S for secondary. I want a query to make sure each household has only 1 Primary record (P). Also, check to make sure there are NO HHLDs that only have Secondary record (S). Key is hhldkey. Ex: below failed b/c 2 primarys in 1 hhld. Hhldkey/Cust_type. (Fails b/c 2. Primarys in hhld) 1/P 1/P 1/S Hhldkey/Cust_type (fails b/c no primary in hhld) 2/S 2/S Hhldkey/cust_type (pass b/c only 1 primary) 3/P 3/S 3/S
sql 2012
1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

ThomasRushton avatar image ThomasRushton ♦♦ commented ·
Could give us some sample tables / data etc, so we would be able to have a stab at this in a way that matches your expectations?
0 Likes 0 ·

1 Answer

·
Kev Riley avatar image
Kev Riley answered
Is this an existing table with existing data that you want to find? Or do you want a design that doesn't allow it in the first place? Lets take the first scenario: **existing data** Set up some test data use tempdb; --this table will allow the 'bad' data create table tempdb..HouseHold_Allow (Hhldkey int, Cust_type char(1)) insert into tempdb..HouseHold_Allow select 1,'P' insert into tempdb..HouseHold_Allow select 1,'P' insert into tempdb..HouseHold_Allow select 1,'S' insert into tempdb..HouseHold_Allow select 2,'S' insert into tempdb..HouseHold_Allow select 2,'S' insert into tempdb..HouseHold_Allow select 3,'P' insert into tempdb..HouseHold_Allow select 3,'S' insert into tempdb..HouseHold_Allow select 3,'S' Now this query will give you all those Hhldkey values that break the rules. It does this by finding all those Hhldkey values where there is one and only 1 row for the 'P', and then comparing those to all Hhldkey values. select distinct Hhldkey from tempdb..HouseHold_Allow where Hhldkey not in ( select Hhldkey from tempdb..HouseHold_Allow where Cust_type = 'P' group by Hhldkey having count(Hhldkey) = 1 ) go If you want to design a table that does not allow this data, then this is more interesting! Lets setup our table --this table will not allow the 'bad' data create table tempdb..HouseHold_NotAllow (Hhldkey int, Cust_type char(1)) go Now for the first rule of only one 'P' then this can be easily constrained by adding a **unique, filtered** index. We create an index that only looks at the 'P' rows, and make it unique. create unique index UFX_HouseHold_NotAllow on HouseHold_NotAllow (Hhldkey, Cust_type) where Cust_type = 'P' go To enforce the rule that there must be a primary, I've decided to create a trigger. This trigger will rollback the transaction if it finds a 'S' row without a 'P' row - the details of exactly what you want to check for and how to handle it I'll leave up to you. create trigger CheckOnePrimary on dbo.HouseHold_NotAllow for insert, update as if exists( select Hhldkey, Cust_type from dbo.HouseHold_NotAllow where Cust_type = 'S' and Hhldkey not in (select Hhldkey from dbo.HouseHold_NotAllow where Cust_type = 'P') ) begin raiserror ('Cannot have a Houshold without a Primary', 16, 1); rollback transaction; end go So now if we try to add rows with 2 'P' rows insert into tempdb..HouseHold_NotAllow select 1,'P' insert into tempdb..HouseHold_NotAllow select 1,'P' insert into tempdb..HouseHold_NotAllow select 1,'S' we will get an error Msg 2601, Level 14, State 1, Line 48 Cannot insert duplicate key row in object 'dbo.HouseHold_NotAllow' with unique index 'UFX_HouseHold_NotAllow'. The duplicate key value is (1, P). The statement has been terminated. Be aware though that 2 of these rows will still make it into the table, it's only the 2nd 'P' that fails - if you wanted the whole batch to fail you would have to handle that in a transaction. Try and add 'S' rows without a 'P' insert into tempdb..HouseHold_NotAllow select 2,'S'; insert into tempdb..HouseHold_NotAllow select 2,'S'; gives us Msg 50000, Level 16, State 1, Procedure CheckOnePrimary, Line 61 Cannot have a Houshold without a Primary Msg 3609, Level 16, State 1, Line 51 The transaction ended in the trigger. The batch has been aborted. but the valid data is fine insert into tempdb..HouseHold_NotAllow select 3,'P'; insert into tempdb..HouseHold_NotAllow select 3,'S'; insert into tempdb..HouseHold_NotAllow select 3,'S';
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.