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.
| Author |
Topic |
|
Donny Bahama
Starting Member
13 Posts |
Posted - 2006-06-20 : 18:33:21
|
| My database (MS SQL2K) is used primarily for the entry, tracking and reporting of (software) QA test results. This query is used to poulate a test matrix page - columns represent supported platforms, rows represent test cases. Each cell is a link to the data entry page where the test case and platform are prepopulated. (Also prepopulated - from a cookie - are test date, build, language, locale and QA engineer, so that only pass or fail+severity and defect # need to be entered.) Submit returns the user to the updated matrix page, which is populated by the query in question, here...For each combination of test case and supported platform, I need one record to be returned - even if there's no data in the TestResults table for some combinations. If there is data I want the query to return TestCase, Platform, TestDate, Build, QAEngineer and Result for the most recent test result (using MAX statements for Build and TestDate) - BUT, for combinations of test case/platform that have not yet been tested, is there some way to tell the query to return a record with "UNTESTED" (or even NULL) values for each (or even the first) field in the record? |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2006-06-20 : 19:01:18
|
| you need a CROSS JOIN. see if this helps:http://weblogs.sqlteam.com/jeffs/archive/2005/09/12/7755.aspx |
 |
|
|
cmdr_skywalker
Posting Yak Master
159 Posts |
Posted - 2006-06-20 : 22:43:43
|
| Please specify the tables, columns, sample data. You may use combination of LEFT JOIN/RIGHT JOIN/INNER JOIN. See the BOL for more info.May the Almighty God bless us all! |
 |
|
|
jen
Master Smack Fu Yak Hacker
4110 Posts |
Posted - 2006-06-21 : 02:29:15
|
| like a select...case?--------------------keeping it simple... |
 |
|
|
Donny Bahama
Starting Member
13 Posts |
Posted - 2006-06-21 : 14:14:52
|
quote: Originally posted by jsmith8858 you need a CROSS JOIN. see if this helps:http://weblogs.sqlteam.com/jeffs/archive/2005/09/12/7755.aspx
Thanks for that, Jeff. Eventually, it may help (once I get to where I can understand it all!)The problem(s) with using that (to the extent that I understand it) are... - I'm querying a single table - TestResults. While I do have a TestCases table and a Platforms table, a cross join of those would A. Yield no test results (because those are stored only in the TestResults table) and B. Would yield invalid test case:platform combinations unless I use a WHERE clause to narrow down platforms appropriately.
- Even if I can get the right combinations of CROSS and LEFT/RIGHT/INNER/OUTER to return something for each test case:platform combination, I actually have multiple records for many of the combinations. (E.g. the test case "1101-Installation" has been tested on XPP-2 (XP Pro, SP2) on virtually every build since the start of system test.) Still, I guess this could make a good subquery and I could use MAX(TestDate) and MAX(Build) to return the recordset I need.
This really drives home what a SQL novice I am! Up to now, all my JOINs have been INNER. I was getting by nicely by creating TestResults.Result="untested" records for each test case:platform combo, but now that I've elected to throw Language and Locale into the mix, I either need thousands of such "untested" records (the wrong way) or I need to understand all this CROSS/OUTER JOIN stuff (the right way.) What a great learning opportunity! Thanks to everyone for your interest and guidance! |
 |
|
|
Donny Bahama
Starting Member
13 Posts |
Posted - 2006-06-21 : 14:18:45
|
quote: Originally posted by cmdr_skywalker Please specify the tables, columns, sample data.
I'm going to play with combinations of CROSS and OUTER joins (so I can learn from it) - ideally, I'd like to figure this out on my own using info from Jeff's blog post, but I'll post tables, columns and sample data shortly (in case anyone wants a real challenge, here! ) |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2006-06-21 : 16:17:22
|
| Donny -- read the article. It does everything you need. You start with a cross join, and then left outer join to a derived table that has your data all summarized. replace NULLS with 0 or whatever you need.If the article isn't clear, let me know. |
 |
|
|
Donny Bahama
Starting Member
13 Posts |
Posted - 2006-06-21 : 22:54:58
|
OK, Jeff. I read the article and it basically made sense and I was basically able to draw the connections between the example given and my database. (Though in the process I think I may have busted a couple of the teeth on the gears in my brain!)  SELECT ISNULL(oj.Result, 'UNTESTED') AS Result, ISNULL(tc.Number, 'UNTESTED') AS TCnum, ISNULL(p.OS, 'UNTESTED') AS OS, oj.Build, oj.ID, oj.TestDate, oj.Engineer, oj.FullName AS TestCase, oj.Weight, p.OSbitmaskFROM TestCases tc CROSS JOIN Platforms p LEFT OUTER JOIN (SELECT tr.TestCase, tr.OS, tr.Build, tr.ID, tr.TestDate, tr.Engineer, tr.Result, tr.TR, tr.Project, tc.FullName, fc.Weight FROM TestResults tr INNER JOIN TestCases tc ON tr.TestCase = tc.Number AND tr.Project = tc.Project INNER JOIN FuncComps fc ON LEFT(tr.TestCase, 2) = fc.Number WHERE (tr.Project = 'av09120000')) oj ON tc.Project = oj.Project AND tc.Number = oj.TestCase AND p.OS = oj.OSWHERE (tc.Project = 'av09120000') AND (p.OSbitmask IN (1, 16, 64))ORDER BY oj.Weight DESC, tc.Number, p.OSbitmask, oj.Build DESC, oj.ID DESC Amazingly (to me), the query above actually works. HOWEVER... if you notice the ORDER BY clause, I'm sorting first on oj.(FuncComps.)Weight.The purpose of this field - and the entire FuncComps table is to "weight" the test cases (each test case belongs to a particular functional component of the application - installation, licensing, menus, toolbars, etc.) so that they are displayed in order with the most critical test cases at the top. Test cases at the bottom are either related to mature, stable code or to features not commonly used by most customers or are likely to have a low impact in the event a bug slips through, so we test from top to bottom, knocking out as many tests as time allows.The problem is that, for the purpose of parsing the recordset and displaying (via ASP) the test matrix, I expect to see results in groups of 3 (supported platforms) or more (there are frequently multiple results for a single test case/platform combo. But whenever ISNULL works it's magic for me, I get a NULL weight which causes the recordset to sort unexpectedly.I still need to use MAX(Build) AS Build and MAX(ID) AS ID to pull the "top" value from multiple results for a single test case:platform pair, so I'm going to make the above a subquery and select from it. As long as I'm doing that, I can strip out the Weight field (and any others that I'll no longer need since I can't properly sort this recordset anyway) then I'll JOIN the tables and fields I need for proper sorting as part of the main query. (If there's a better way to go about this, please let me know!)I know that an INNER JOIN won't work here, but I'm not sure what will. (This is what I meant by realizing what a complete novice I am - I've never used anything but INNER JOINS up to now, and I'm not even sure what LEFT/RIGHT/OUTER JOINS do! I'll figure it out, though! )Thanks so much for all your help. I'm learning SO MUCH! This is awesome!I'm the guy who's not afraid to ask the painfully stupid questions! |
 |
|
|
Donny Bahama
Starting Member
13 Posts |
Posted - 2006-06-23 : 11:28:50
|
IT WORKS!!!  SELECT sq.ID, sq.TestCase, tc.FullName, sq.OS, ISNULL(tr.Build, 0) AS Build, ISNULL(tr.Engineer, 'Nobody') AS Engineer, ISNULL(tr.TestDate, '5/1/2006') AS TestDate, ISNULL(tr.Result, 'UNTESTED') AS Result, ISNULL(tr.TR, 'N/A') AS TR, pf.OSbitmask, fc.WeightFROM (SELECT tc.Number AS TestCase, pf.OS, ISNULL(oj.ID, 0) AS ID FROM TestCases tc CROSS JOIN Platforms pf LEFT OUTER JOIN (SELECT tr.TestCase, tr.OS, MAX(tr.Build) AS Build, MAX(tr.ID) AS ID FROM TestResults tr WHERE (tr.Project = 'av09120000') AND (tr.Lang = 'USEng') AND (tr.Locale = 'EU') GROUP BY tr.TestCase, tr.OS) oj ON tc.Number = oj.TestCase AND pf.OS = oj.OS WHERE (pf.OSbitmask IN (1, 16, 64))) sq LEFT OUTER JOIN TestResults tr ON tr.ID = sq.ID LEFT OUTER JOIN Platforms pf ON pf.OS = sq.OS LEFT OUTER JOIN TestCases tc ON sq.TestCase = tc.Number LEFT OUTER JOIN FuncComps fc ON LEFT(sq.TestCase, 2) = fc.Number LEFT OUTER JOIN Projects pj ON tr.Project = pj.IDORDER BY fc.Weight DESC, sq.TestCase, pf.OSbitmask I can even extend it somewhat by specifying different values for tr.Lang and tr.Locale to show dedicated test matrices for localization/globalization testing!What I can't seem to do - no matter where I try to insert the clause - is to narrow down the records returned by the CROSS JOIN of TestCases and Platforms. This is something I really need to be able to do, because sometimes you only want to see results for "high priority" test cases or because when doing localization testing, we only want to test a subset of test cases.I tried creating (yet another) subquery and substituting it for the TestCases table... (SELECT... FROM... INNER JOIN blah blah WHERE yada yada) tc CROSS JOIN Platforms pf LEFT OUTER JOIN (SELECT... but, while running it by itself gave me the list of test cases I was expecting, when inserted it into the main query, it refused to JOIN any of the data from the TestResults table.I've tried this every way I can think of. I'd sure appreciate some suggestions.-------------------------------------------------------------------I'm the guy who's not afraid to ask the painfully stupid questions! |
 |
|
|
Donny Bahama
Starting Member
13 Posts |
Posted - 2006-06-23 : 13:18:05
|
I FIGURED IT OUT! (I'm starting to amaze myself! )SELECT sq.ID, sq.TestCase, tc.FullName, sq.OS, ISNULL(tr.Build, 0) AS Build, ISNULL(tr.Engineer, 'Nobody') AS Engineer, ISNULL(tr.TestDate, '5/1/2006') AS TestDate, ISNULL(tr.Result, 'UNTESTED') AS Result, ISNULL(tr.TR, 'N/A') AS TR, pf.OSbitmask, fc.WeightFROM (SELECT tq.Number AS TestCase, pf.OS, ISNULL(oj.ID, 0) AS ID FROM (SELECT t.Number FROM TestCases t INNER JOIN FuncComps fc ON fc.Number = LEFT(t.Number, 2) INNER JOIN Projects pj ON pj.ID = t.Project AND fc.Weight > 1 WHERE (t.Project = 'av09120000')) tq CROSS JOIN Platforms pf LEFT OUTER JOIN (SELECT tr.TestCase, tr.OS, MAX(tr.Build) AS Build, MAX(tr.ID) AS ID FROM TestResults tr WHERE (tr.Project = 'av09120000') AND (tr.Lang = 'USEng') AND (tr.Locale = 'EU') GROUP BY tr.TestCase, tr.OS) oj ON tq.Number = oj.TestCase AND pf.OS = oj.OS WHERE (pf.OSbitmask IN (1, 16, 64))) sq LEFT OUTER JOIN TestResults tr ON tr.ID = sq.ID LEFT OUTER JOIN Platforms pf ON pf.OS = sq.OS LEFT OUTER JOIN TestCases tc ON sq.TestCase = tc.Number LEFT OUTER JOIN FuncComps fc ON LEFT(sq.TestCase, 2) = fc.Number LEFT OUTER JOIN Projects pj ON tr.Project = pj.IDORDER BY fc.Weight DESC, sq.TestCase, pf.OSbitmask I'm not sure why replacing TestCases (in the CROSS JOIN) with a subquery didn't work last night, but I got it working today. From here, I should be able to do pretty much anything I need to do by adjusting the tq subquery. WOOT!Thanks again for the help!---------------------------------------------------------------I'm the guy who's not afraid to ask the painfully stupid questions! |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2006-06-23 : 16:25:28
|
| Nice job, sorry I didn't get back to you until now, it's been busy at work .... by working this out, you have learned a lot about sql -- when to use cross joins, derived tables, where to put criteria, outer joins, etc -- so it is a great exercise to go through. Well done! |
 |
|
|
Donny Bahama
Starting Member
13 Posts |
Posted - 2006-06-23 : 17:58:34
|
| Thanks, Jeff - for the help, for the excellent CROSS JOIN article, and for being active on this forum!---------------------------------------------------------------I'm the guy who's not afraid to ask the painfully stupid questions! |
 |
|
|
Donny Bahama
Starting Member
13 Posts |
Posted - 2006-09-26 : 18:35:20
|
I've just figured out that my query doesn't work after all...It seems that this: SELECT tr.TestCase, tr.LogOS as OS, MAX(tr.Build) AS Build, MAX(tr.ID) AS ID FROM TestResults tr WHERE (tr.Project = 'av09120000') AND (tr.Lang = 'USEng') AND (tr.Locale = 'EU') GROUP BY tr.TestCase, tr.LogOS does return the MAX build number and the MAX ID - but they are not necessarily from the same record! This messes up everything. I tried using ID in the select statement (without the MAX) and adding it to the group by, but that returns multiple records per TestCase/OS combination. (With MAX(tr.ID) AS ID, it returns only one record per combination - albeit an erroneous record, since the ID is not the one from the record containing the desired MAX(build) value.What do I do, here?---------------------------------------------------------------I'm the guy who's not afraid to ask the painfully stupid questions! |
 |
|
|
|
|
|
|
|