Ok, here's the deal. I'm interfacing with an AS400 using JDBC, and I have a file with all these records. What happens is, when the people manufacturing do a quality test they sign off using the computer and it writes a record that looks like this: Order#, Employee#, QA_Test_Type, Date, Time, etc. So they are supposed to perform four types of tests on every order. So there will be 4 records for order X. One each of QA_Test_Type MFGS, MFG1, MFG2, and MFG3. I need a query that will return the Order#s that DON'T have all 4 of those (i.e. they didn't do test MFG2). I tried using Grouping, but that didn't work. The closest I came was getting a list the orders that did have all of tests done by using UNION. Then I was going to make that a subquery and say Where QA_Test_Type NOT IN (This list), but it won't let me use a UNION query as a subquery for some reason. Any thoughts? Basically need a list of all Order#s that don't have all four QA_Test_Type records. And I can't do anything with returned row counts because there are optional rows that could be there.
UPDATE: Ok, thanks to all your help, and combining ideas, I came up with an SQL query that reports only the ones that don't have all 4 MFG? records. MFG3 is the final check, so we don't want to include the ones that don't have that in the list, since they are still being manufactured. Here it is:
SELECT * FROM SFMP00 t0 WHERE t0.Type = 'MFG3' AND t0.OrdNo NOT IN (SELECT t1.OrdNo FROM SFMP00 t1 JOIN SFMP00 t2 ON t1.OrdNo = t2.OrdNo JOIN SFMP00 t3 ON t1.OrdNo = t3.OrdNo JOIN SFMP00 t4 ON t1.OrdNo = t4.OrdNo WHERE t1.Type = 'MFGS' AND t2.Type = 'MFG1' AND t3.Type = 'MFG2' AND t4.Type = 'MFG3') ORDER BY OrdNo
Special thanks to johndiii, since his was fastest as worked best, and became the base of the above. I'll try to pull some strings and get you some more DragonPointses... ;-)
Something like (Score:2)
MFGS is NULL OR MFG1 is NULL OR MFG2 is NULL or MFG3 is NULL
The SQL might look something like this
Depending on the data in the fields you might have to testr for
Re:Something like (Score:2)
ORDER# - TYPE - EMPLOYEE# - DATE - TIME
12 - MFGS - 00598 - 10122003 - 135403
13 - MFGS - 00315 - 10122003 - 135445
12 - MFG1 - 00598 - 10122003 - 140145
12 - MFG2 - 00598 - 10122003 - 142205
etc.
Idiot perl jockey here (Score:2)
Perl/php aren't strongly typed (by default), a boolean, a string, and a scalar are all one in the same, so you can just do a bool test on all four fields, if they are all there, all are true, if one is null/empty, it would be false, that could be your flag.
Use a join to get the list (Score:1)
Or something like that, anyway. Since I don't
Re:Use a join to get the list (Score:1)
Re:Use a join to get the list (Score:2)
I like that one... (Score:2)
One comment: NOT EXISTS is frequently a better performing operator than NOT IN. Of course, my experience is strictly in the Oracle world, so that may not translate well outside of Oracle.
From the description, it seems that OrderNum and QA_Test_Type form a composite primary key? Are they declared as such? (Do they have a unique constraint and and index?) If not this is going to result in some hellacious full table scans.
Re:I like that one... (Score:2)
Re:Use a join to get the list (Score:2)
Taking a different route? (Score:2)
Would it be faster to perform four discreet subqueries instead of dealing with the relationships? The additional overhead of comparing the four tables in the subquery is avoided this way, but I suppose it depends on the overhead of IN as well. Something like this:
SELECT * FROM SFMP00
WHERE OrdNo NOT IN
(SELECT OrdNo FROM SFMP00
WHERE type = "MFGS")
AND OrdNo NOT IN
(SELECT OrdNo FROM SFMP00
WHERE type = "MFG1")
AND OrdNo NOT IN
(SELECT OrdNo FROM SFMP00
Re:Taking a different route? (Score:2)
Re:Taking a different route? (Score:2)
I think you want to use ORs instead. That query will return OrdNo where no test have been perfomred.
The real answer to your question is "It depends!" Ideally, your SQL engine should optimize that expression just as well as the one that johndiii proposed. Back here in the real world, you'd probably need to benchmark to be sure. Different SQL products will work differently. Within a single SQL product like Oracle, it would depend on your selection of Cost or Rule based optimization, the accuracy of the
OR (Score:2)
Don't make a mistake without one.
I had another layer of subquery in there, and thought that it was irrelevant, so I just trimmed it. Ah, well.
Re:Taking a different route? (Score:2)
Re:Taking a different route? (Score:2)
I'm an Oracle guy so... (Score:2)
SELECT DISTINCT t.order_id
FROM tests t
, tests ts
, tests t1
, tests t2
, tests t3
WHERE t.order_id = ts.order_id(+)
AND t.order_id = t1.order_id(+)
AND t.order_id = t2.order_id(+)
AND t.order_id = t3.order_id(+)
AND NVL(ts.test_type, 'MFGS') = 'MFGS'
AND NVL(t1.test_type, 'MFG1') = 'MFG1'
AND NVL(t2.test_type, 'MFG2') = 'MFG2'
AND NVL(t3.test_type, 'MFG3') = 'MFG3'
AND ( ts.test_type IS NULL
OR t1.test_type IS NULL
OR t1.test_type IS NULL
OR t1.test_type IS NUL
Hrmm (Score:2)
NOTE: assumes the table is called "file".
SELECT file.order
FROM file
WHERE file.order NOT IN
( SELECT f1.order
FROM file f1, file f2, file f3, file f4
WHERE f2.order = f1.order
AND f3.order = f1.order
AND f4.order = f1.order
AND f1.test_type = "MFGS"
AND f2.test_type = "MFG1"
AND f3.test_type = "MFG2"
AND f4.test_type = "MFG3" );
Everyone else is being too complicated... (Score:2)
SELECT order# FROM tests
GROUP BY order#
HAVING count(order#) 4;
Done.
Re:Everyone else is being too complicated... (Score:2)
Bah, I didn't read your whole post.
Sorry!
Well, this might work:
SELECT order# from tests
WHERE TEST in (MFG1,
GROUP BY order#
HAVING count(order#) < 4.
Re:Everyone else is being too complicated... (Score:2)
SELECT order# from tests
WHERE TEST Like (MFG*)
GROUP BY order#
HAVING count(order#) 4.
Not sure if that is the proper syntax for the wildcard in what you use.
Re:Everyone else is being too complicated... (Score:2)
However, the TEST IN (MFG1, MFG2,