| Author |
Topic |
|
obiron
Starting Member
23 Posts |
Posted - 2009-05-27 : 07:04:31
|
Hi guys,This could be a tricky one and I am not even sure whether it is possible.Lets say I have a sales analysis table, a budgets table and a sales-budgets mapping table.Sales analysis holdsSaleman IDSalesman TeamProduct IDProduct GroupCustomer IDCustomer Classification(there would be other data for summing and aggregating - order ID, Order Line ID, Qty, price, etc..)The Budget table holdsBudget Line #Budget codeBudget valueThe Cross Reference table holdsSales Team IDProduct GroupCustomer ClassificationBudget Line #Lets say that sales teams are North, South, East, West, MidlandsLets say that Product Groups are Bearings, Shafts, Pumps and anything else gets lumped in togetherLets stay that Customer classes are Gold,Silver,BronzeFor Pumps the budgets are set by Team and Customer classesFor Shafts, Budgets are set by Customer ClassesFor Bearings, Budgets are set by Teamthe X-ref Table Looks like thisTeam Product Cust BudgetLine#North Pumps Gold 1South Pupms Gold 2East Pumps Gold 3West Pumps Gold 4Mids Pumps Gold 5North Pumps Silver 6South Pupms Silver 7East Pumps Silver 8West Pumps Silver 9Mids Pumps Silver 10North Pumps Bronze 11South Pupms Bronze 12East Pumps Bronze 13West Pumps Bronze 14Mids Pumps Bronze 15NULL Shafts Gold 16NULL Shafts Silver 17NULL Shafts Bronze 18North Bearings NULL 19South Bearings NULL 20East Bearings NULL 21West Bearings NULL 22Mids Bearings NULL 23NULL NULL NULL 24 // captures all other sales I want to create a SELECT statement that joins the Sales Analysis to the X-ref table to give me the budget line number so that I can then join to the budgets table.Has anyone else had to do this where the values are potentially NULL in your right hand table and you have multiple join values.Current plan is to doSELECT S.* X.BudgetLineNumber, B.BudgetCodeFROM Sales S JOIN X_ref X ON S.Team = coalesce(X.Team,S.Team) AND S.ProdGroup = coalesce(X.ProdGroup,S.Prodgroup) AND S.CustType = coalesce(X.CustType,S.CustType) JOIN Budgets B ON B.BudgetLineNumber = X.BudgetLineNumber What happens if there are multiple matching records when NULLs are applied (e.g. Customer has been classified as 'TIN' and product has been classified as 'FLANGE' and Team has been identified as 'SPECIAL'and the X-ref lines existNULL,NULL,TIN,32NULL,FLANGE,NULL,35SPECIAL,FLANGE,NULL,37SPECIAL,NULL,NULL,38All of these lines will match the selection criteria. Does it then matter which order the join conditions are presented or will all lines match regardless. |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2009-05-27 : 07:18:56
|
All lines will match.You have to decide which business rule to apply for only returning one record of those 4 above.Which combinations, hits, are more worth? E 12°55'05.63"N 56°04'39.26" |
 |
|
|
obiron
Starting Member
23 Posts |
Posted - 2009-05-27 : 08:42:36
|
| So I will need to Add a ranking factor to the X_ref table,rewrite it as a sub query ordered by ranking factorSelect TOP 1 |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2009-05-27 : 08:45:39
|
Or use the built-in ROW_NUMBER() function to get the highest ranked record. E 12°55'05.63"N 56°04'39.26" |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2009-05-27 : 09:59:02
|
| according to you, what should you be getting out of above four rows? |
 |
|
|
obiron
Starting Member
23 Posts |
Posted - 2009-05-28 : 08:07:51
|
| Thats the $64000 question.I know I only want to return 1 match in the X_ref table for each row in the sales table but I don't know which one, and it may be different rankings for different sales combinations.I am probably safe to say that I want to return an exact match first, then a match with only 1 NULL, then a match with 2 NULLs etc..But it is how you decide which NULL takes precedence.The example given above is theoretical, the production solution will have at least 8 and possibly 12 elements to the X_ref table.I could have another table that ranks the elements that is then used to build the order by clause in the SQL and call it using sp_executeSQL() but that is starting to get nasty :( |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2009-05-28 : 08:31:27
|
This is one way. I also took the liberty to make the three different columns Team, Product and Cust weighted.It means in this suggstion that a match on Team column is worth more, it has a weight of 4 and a match on Product column has a weight of 2.DECLARE @CrossRef TABLE ( Team VARCHAR(20), Product VARCHAR(20), Cust VARCHAR(20), BudgetLine INT, HitWeight AS COALESCE(4 * SIGN(LEN(Team)), 0) + COALESCE(2 * SIGN(LEN(Product)), 0) + COALESCE(1 * SIGN(LEN(Cust)), 0) )INSERT @CrossRefSELECT 'North', 'Pumps', 'Gold', 1 UNION ALLSELECT 'South', 'Pumps', 'Gold', 2 UNION ALLSELECT 'East', 'Pumps', 'Gold', 3 UNION ALLSELECT 'West', 'Pumps', 'Gold', 4 UNION ALLSELECT 'Mids', 'Pumps', 'Gold', 5 UNION ALLSELECT 'North', 'Pumps', 'Silver', 6 UNION ALLSELECT 'South', 'Pumps', 'Silver', 7 UNION ALLSELECT 'East', 'Pumps', 'Silver', 8 UNION ALLSELECT 'West', 'Pumps', 'Silver', 9 UNION ALLSELECT 'Mids', 'Pumps', 'Silver', 10 UNION ALLSELECT 'North', 'Pumps', 'Bronze', 11 UNION ALLSELECT 'South', 'Pumps', 'Bronze', 12 UNION ALLSELECT 'East', 'Pumps', 'Bronze', 13 UNION ALLSELECT 'West', 'Pumps', 'Bronze', 14 UNION ALLSELECT 'Mids', 'Pumps', 'Bronze', 15 UNION ALLSELECT NULL, 'Shafts', 'Gold', 16 UNION ALLSELECT NULL, 'Shafts', 'Silver', 17 UNION ALLSELECT NULL, 'Shafts', 'Bronze', 18 UNION ALLSELECT 'North', 'Bearings', NULL, 19 UNION ALLSELECT 'South', 'Bearings', NULL, 20 UNION ALLSELECT 'East', 'Bearings', NULL, 21 UNION ALLSELECT 'West', 'Bearings', NULL, 22 UNION ALLSELECT 'Mids', 'Bearings', NULL, 23 UNION ALLSELECT NULL, NULL, NULL, 24DECLARE @Sample TABLE ( RowID INT IDENTITY(1, 1), Team VARCHAR(20), Product VARCHAR(20), Cust VARCHAR(20) )INSERT @SampleSELECT 'North', 'Pumps', 'Gold' UNION ALLSELECT 'North', 'Pumps', 'Silver'SELECT *FROM ( SELECT s.*, cr.BudgetLine, ROW_NUMBER() OVER (PARTITION BY s.RowID ORDER BY cr.HitWeight DESC) AS recID FROM @Sample AS s INNER JOIN @CrossRef AS cr ON COALESCE(cr.Team, s.Team) = s.Team AND COALESCE(cr.Product, s.Product) = s.Product AND COALESCE(cr.Cust, s.Cust) = s.Cust ) AS dWHERE recID = 1ORDER BY RowID E 12°55'05.63"N 56°04'39.26" |
 |
|
|
|
|
|