sql join -vs- where clause not producing the same result? - sql-server-2005

I am a bit boggled as to why these two SQL constructs do not yield the same result.
SQL#1 return 2 identical records (dups) when only one exists in the defects table... see next sql
SELECT *
FROM Defects d
JOIN StatusCode C ON C.CodeName = d.Status AND c.scid = 10
WHERE d.AssignedTo='me'
SQL#2 reruns 1 record - this is correct cause lookign at raw data there is one defect not closed for 'me'
SELECT *
FROM Defects d
WHERE d.AssignedTo='me' AND Status <> 'closed'
all i am doing is instead of using a negative where status not in something , using a positive by way of the join to records that have every value defect status other than closed
why does this happen, and how can i alter my select with the join to corect its result. i tried using DISTINCT but it fails with:
The ntext data type cannot be selected
as DISTINCT because it is not
comparable.
there are no status codes that are 'closed', not a single one:
select * from StatusCode where scid = 10
results in these values:
Fixed
New
Ready for Retest
Failed Retest
Quality Follow Up
Reopen
Rejected
Consumer
In Coding
Open
Fixed
New
Ready for Retest
Failed Retest
Quality Follow Up
Reopen
Rejected
Consumer
In Coding
Open

The inner join will return all matching combinations of rows, so there must be two rows in the StatusCode table that match the "Status" value of your Defect (and have scid = 10).
FixedNewReady for RetestFailed RetestQuality Follow UpReopenRejected ConsumerIn CodingOpenFixedNewReady for RetestFailed RetestQuality Follow UpReopenRejected ConsumerIn CodingOpen
Not sure if I parsed your list exactly right, but there do appear to be duplicates. The answer, then, is to either eliminate the duplicates in the StatusCode table, or apply an additional filter to distinguish between them if the duplicates are valid.

How many rows are returned by this?
SELECT * FROM StatusCode C WHERE c.scid = 10
You may therefore want to do this:
SELECT *
FROM Defects d
WHERE d.AssignedTo='me' AND d.Status IN (
SELECT C.CodeName FROM StatusCode C WHERE C.scid = 10
)
Edit to address your edit: since you have multiple states with scid=10, each of those will be joined to your rows, which is why you get the duplicates. My code suggestion is still valid though.

I would think the problem is here:
JOIN StatusCode C ON C.CodeName = d.Status AND c.scid = 10
The c.scid = 10 should be in the where clause.

Related

How to join 2 tables with multiple conditions each?

I have data split between 2 tables, and need to join the necessary data together for analysis.
One table Test 3 Output contains ID numbers, and the return value of the test. The other table Test Results contains the same IDs, along with their corresponding serial number and overall test result.
I need to combine these into a single table that just displays ID, serial number and test value.
Sorry in advance for the horrible SQL thats about to follow, I'm brand new to this.
I have 2 working queries that give me what I want, but I can't seem to join them together.
The first query:
select `ID`,`Serial Number` from `Test Results`t where (len(`Serial Number`)=16 and FailMode = '24V Supply FAIL')
This gets me the ID and serial number of all the tests that failed '24V supply'. It also filters out garbage serial numbers as the correct ones should have 16 digits.
The second query:
select `ID` from `Test 3 Output`o where o.`24V Supply (V)`<30
This gets me the ID and test results, and filters out some results that were greater than 30V. Note that '24V Supply(V) is the name of the column containing the test results.
Now when I try to join these with the ID, I get a syntax error. Here's what I tried:
select `ID`,`Serial Number`
from `Test Results`t
where (len(`Serial Number`)=16 and FailMode = '24V Supply FAIL')
left join (`Test 3 Output`o ON t.`ID` = o.`ID` where o.`24V Supply (V)`<30)
This gives the error:
Error: Syntax error (missing operator) in query expression (len(`Serial Number`)=16 and FailMode = '24V Supply FAIL') left join (`Test 3 Output`o ON t.`ID` = o.`ID` where o.`24V Supply (V)`<30)
I'm not sure what operator I'm missing but I had a feeling its related to the fact there's two where statements?
Can anyone offer some help?
Edit: I found a workaround since I can't use 2 where clauses with a join. I created 2 views with my 2 separate queries, and performed the join on those which got me what I wanted. I'd still like to hear a proper way of doing it though :)
You can join 2 subqueries like this:
SELECT q1.a, q1.b, q2.c
FROM (
(SELECT a, b FROM table1
WHERE b > 10) AS q1
LEFT JOIN
(SELECT a, c FROM table2
WHERE c > 20) AS q2
ON q1.a = q2.a
)
Doing the subqueries as separate query objects is easier to debug, but the query objects keep piling up...

Sub-query works but would a join or other alternative be better?

I am trying to select rows from one table where the id referenced in those rows matches the unique id from another table that relates to it like so:
SELECT *
FROM booklet_tickets
WHERE bookletId = (SELECT id
FROM booklets
WHERE bookletNum = 2000
AND seasonId = 9
AND bookletTypeId = 3)
With the bookletNum/seasonId/bookletTypeId being filled in by a user form and inserted into the query.
This works and returns what I want but seems messy. Is a join better to use in this type of scenario?
If there is even a possibility for your subquery to return multiple value you should use in instead:
SELECT *
FROM booklet_tickets
WHERE bookletId in (SELECT id
FROM booklets
WHERE bookletNum = 2000
AND seasonId = 9
AND bookletTypeId = 3)
But I would prefer exists over in :
SELECT *
FROM booklet_tickets bt
WHERE EXISTS (SELECT 1
FROM booklets b
WHERE bookletNum = 2000
AND seasonId = 9
AND bookletTypeId = 3
AND b.id = bt.bookletId)
It is not possible to give a "Yes it's better" or "no it's not" answer for this type of scenario.
My personal rule of thumb if number of rows in a table is less than 1 million, I do not care optimising "SELECT WHERE IN" types of queries as SQL Server Query Optimizer is smart enough to pick an appropriate plan for the query.
In reality however you often need more values from a joined table in the final resultset so a JOIN with a filter WHERE clause might make more sense, such as:
SELECT BT.*, B.SeasonId
FROM booklet_tickes BT
INNER JOIN booklets B ON BT.bookletId = B.id
WHERE B.bookletNum = 2000
AND B.seasonId = 9
AND B.bookletTypeId = 3
To me it comes down to a question of style rather than anything else, write your code so that it'll be easier for you to understand it months later. So pick a certain style and then stick to it :)
The question however is old as the time itself :)
SQL JOIN vs IN performance?

Query does execute without errors, but returns no output

My query here has a sub-query in it but it returns no output, but in reality it has to give some output because I manually checked and output exists.I have posted the query below.
select mac.mac_id,mac.mac1,mac.mac_type,record.soc_id
from mso_charter.mac
join record on mac.record_id = record.record_id
where mac.mac_type='ethB' and record.soc_id IN (select soc from d);
Sample data is below
mac_id mac1 mac_type record_id--- for table mac
1 6142 ethA 1
2 6412 ethB 1
3 2313 ethC 1
record_id soc_id ---- for table record
1 Qu132
1 as432
1 342aq
soc --- for table d
a12w2
23we
qw12
mso_charter is the schema name mac,d and record is the table name.
Note that your subquery is actually still a join and can be written that way:
select mac.mac_id,mac.mac1,mac.mac_type,record.soc_id
from mso_charter.mac
join record using(record_id)
join d on record.soc_id = d.soc
where mac.mac_type='ethB';
As per the comment we still need a data set to reproduce and help.
Should be select soc_id from d instead of select select soc from d
According to your sample data, d has a column soc_id. That should be used for the comparison:
select m.mac_id, m.mac1, m.mac_type, r.soc_id
from mso_charter.mac m join
record r
on m.record_id = r.record_id
where m.mac_type = 'ethB' and
r.soc_id in (select d.soc_id from d);
It is possible that ids look the same but are not, because of international characters, hidden characters, spaces in the wrong place, and so on.
If this doesn't work then try the following:
Remove the soc_id condition and see if any rows match the first condition and join.
If that still returns nothing, remove the entire where clause to see if anything matches the join.
None of your record.soc_id match any of your d.soc_id. So you get no row.
Also, you write select soc from d. soc, not soc_id. Typo or error?
So, thanks to all who tried helping me in this situation. I actually had did a very silly mistake.The reason I am posting the right answer is probably because if someone else in future get stuck in such a issue or something similar it would be helpful to them.
select m.mac_id,m.mac,m.mac_type,r.soc_id
from mso_charter.mac m
join mso_charter.record r on m.record_id = r.record_id
where m.mac_type = 'ethB' and r.soc_id IN (select d.soc_id from d);
Mistake was I had not mentioned the schema name while performing join and there were multiple tables named record in other schema's, it was just out of frustration we tend to forget small things which costed me few hours to work over.

how to join multiple tables without showing repeated data?

I pop into a problem recently, and Im sure its because of how I Join them.
this is my code:
select LP_Pending_Info.Service_Order,
LP_Pending_Info.Pending_Days,
LP_Pending_Info.Service_Type,
LP_Pending_Info.ASC_Code,
LP_Pending_Info.Model,
LP_Pending_Info.IN_OUT_WTY,
LP_Part_Codes.PartCode,
LP_PS_Codes.PS,
LP_Confirmation_Codes.SO_NO,
LP_Pending_Info.Engineer_Code
from LP_Pending_Info
join LP_Part_Codes
on LP_Pending_Info.Service_order = LP_Part_Codes.Service_order
join LP_PS_Codes
on LP_Pending_Info.Service_Order = LP_PS_Codes.Service_Order
join LP_Confirmation_Codes
on LP_Pending_Info.Service_Order = LP_Confirmation_Codes.Service_Order
order by LP_Pending_Info.Service_order, LP_Part_Codes.PartCode;
For every service order I have 5 part code maximum.
If the service order have only one value it show the result correctly but when it have more than one Part code the problem begin.
for example: this service order"4182134076" has only 2 part code, first'GH81-13601A' and second 'GH96-09938A' so it should show the data 2 time but it repeat it for 8 time. what seems to be the problem?
If your records were exactly the same the distinct keyword would have solved it.
However in rows 2 and 3 which have the same Service_Order and Part_Code if you check the SO_NO you see it is different - that is why distinct won't work here - the rows are not identical.
I say you have some problem in one of the conditions in your joins. The different data is in the SO_NO column so check the raw data in the LP_Confirmation_Codes table for that Service_Order:
select * from LP_Confirmation_Codes where Service_Order = 4182134076
I assume you are missing an and with the value from the LP_Part_Codes or LP_PS_Codes (but can't be sure without seeing those tables and data myself).
By this sentence If the service order have only one value it show the result correctly but when it have more than one Part code the problem begin. - probably you are missing and and with the LP_Part_Codes table
Based on your output result, here are the following data that caused multiple output.
Service Order: 4182134076 has :
2 PartCode which are GH81-13601A and GH96-09938A
2 PS which are U and P
2 SO_NO which are 1.00024e+09 and 1.00022e+09
Therefore 2^3 returns 8 rows. I believe that you need to check where you should join your tables.
Use DINTINCT
select distinct LP_Pending_Info.Service_Order,LP_Pending_Info.Pending_Days,
LP_Pending_Info.Service_Type,LP_Pending_Info.ASC_Code,LP_Pending_Info.Model,
LP_Pending_Info.IN_OUT_WTY, LP_Part_Codes.PartCode,LP_PS_Codes.PS,
LP_Confirmation_Codes.SO_NO,LP_Pending_Info.Engineer_Code
from LP_Pending_Info
join LP_Part_Codes on LP_Pending_Info.Service_order = LP_Part_Codes.Service_order
join LP_PS_Codes on LP_Part_Codes.Service_Order = LP_PS_Codes.Service_Order
join LP_Confirmation_Codes on LP_PS_Codes.Service_Order = LP_Confirmation_Codes.Service_Order
order by LP_Pending_Info.Service_order, LP_Part_Codes.PartCode;
distinct will not return duplicates based on your select. So if a row is same, it will only return once.

outer query to list only if its rowcount equates to inner subquery

Need help on a query using sql server 2005
I am having two tables
code
chargecode
chargeid
orgid
entry
chargeid
itemNo
rate
I need to list all the chargeids in entry table if it contains multiple entries having different chargeids
which got listed in code table having the same charge code.
data :
code
100,1,100
100,2,100
100,3,100
101,11,100
101,12,100
entry
1,x1,1
1,x2,2
2,x3,2
11,x4,1
11,x5,1
using the above data , it query should list chargeids 1 and 2 and not 11.
I got the way to know how many rows in entry satisfies the criteria, but m failing to get the chargeids
select count (distinct chargeId)
from entry where chargeid in (select chargeid from code where chargecode = (SELECT A.chargecode
from code as A join code as B
ON A.chargecode = B.chargeCode and A.chargetype = B.chargetype and A.orgId = B.orgId AND A.CHARGEID = b.CHARGEid
group by A.chargecode,A.orgid
having count(A.chargecode) > 1)
)
First off: I apologise for my completely inaccurate original answer.
The solution to your problem is a self-join. Self-joins are used when you want to select more than one row from the same table. In our case we want to select two charge IDs that have the same charge code:
SELECT DISTINCT c1.chargeid, c2.chargeid FROM code c1
JOIN code c2 ON c1.chargeid != c2.chargeid AND c1.chargecode = c2.chargecode
JOIN entry e1 ON e1.chargeid = c1.chargeid
JOIN entry e2 ON e2.chargeid = c2.chargeid
WHERE c1.chargeid < c2.chargeid
Explanation of this:
First we pick any two charge IDs from 'code'. The DISTINCT avoids duplicates. We make sure they're two different IDs and that they map to the same chargecode.
Then we join on 'entry' (twice) to make sure they both appear in the entry table.
This approach gives (for your example) the pairs (1,2) and (2,1). So we also insist on an ordering; this cuts to result set down to just (1,2), as you described.