MS access join two tables, get unique rows - sql

This is a modification to a previous question original answer , I hope the proper thing to do is start a new thread.
I have a table called Parts, PartRefID is the PK
PartRefID PartDefID AssemblyID
1 2 c63df10b-8250-4aa5-9889-9e8046331dbf
11 1 db51f4a8-3ffa-41f7-81c1-a9accbbb299a
67 6 136fc5d8-7b65-41b5-bca3-7d4180a1e0ab
77 5 38fa8b7a-2945-4546-8eab-7865a1e515b2
133 2 c63df10b-8250-4aa5-9889-9e8046331dbf
134 6 136fc5d8-7b65-41b5-bca3-7d4180a1e0ab
I need to extract rows with a unique AssemblyID. This was answered by GMB with the following sql:
select *
from parts as p
where [PartRefID] = (
select max(p1.[PartRefID])
from parts as p1
where p1.[AssemblyID] = p.[AssemblyID] and p1.[PartDefID] = 2
)
which worked beautifully. However requirements have changed and I must ignore the PartDefID field and there could also be AssemblyID's which represent parts I do not want.
The AssemblyID's shown in the above table represent an electrical connector part.
Electrical connector parts will ALWAYS have a Partclass of 1 which is defined in another table called PartDefinitions shown here:
PartDefID PartClass PartNumber
1 1 MS27467T23F55P
2 1 330-00186-09
3 2 336-00024-00
4 2 336-00022-00
5 1 MS27468T23F55S
6 1 330-00184-09
with my limited sql knowledge I decided a join was necessary and came up with the following code:
SELECT Parts.*, PartDefinitions.PartClass
From PartDefinitions
INNER Join Parts
On PartDefinitions.PartDefID = Parts.PartDefID
Where (((PartDefinitions.PartClass) = 1))
this gets me close, it produces all the parts in the parts table which are connectors. However there are some duplicate AssemblyID's.
what I need is to produce the following:
PartRefID PartDefID AssemblyID
1 2 c63df10b-8250-4aa5-9889-9e8046331dbf
11 1 db51f4a8-3ffa-41f7-81c1-a9accbbb299a
67 6 136fc5d8-7b65-41b5-bca3-7d4180a1e0ab
77 5 38fa8b7a-2945-4546-8eab-7865a1e515b2
my apologies if I have not made a clear and concise question
thanks for any help
and thanks again GMB

If I understand correctly, you want to filter by the PartClassId in both the subquery and the outer query:
select p.*, pd.PartClass
From Parts as p inner join
PartDefinitions as pd
on pd.PartDefID = p.PartDefID
where pd.PartClassId = 1 and
p.pPartRefID = (select max(p2.pPartRefID)
from parts as p2 inner join
PartDefinitions as pd2
on pd2.PartDefID = pd.PartDefID
where p2.AssemblyID = p.AssemblyID and
p2.PartClassId = 1
)

Related

SQL Query with 2 joins and different values

I'm quite the beginner so I suppose some of you would have an easy time on my task but I need some help:
I have 3 DBs. dbo_A_Personal, dbo_Z_Ferien and dbo_Z_ERFASSUNG
A_Pers has a Pers_ID (LPE_ID) that I can use to join Z_Ferien and Z_ERFASSUNG on.
In Z_Ferien I have 4 rows with that pers_ID and in Z_ERFASSUNG 96.
What I need is a result that has columns that are basically like that:
PersID
Erf
Fer
1224
5
0
1234
4
0
1234
6
0
1234
0
6
so far I have this:
SELECT dbo_A_PERSONAL.LPE_ID, dbo_Z_Ferien.ZFE_TAGE, dbo_Z_ERFASSUNG.ZER_Std100
FROM dbo_A_PERSONAL
INNER JOIN dbo_Z_Ferien ON dbo_A_PERSONAL.LPE_ID = dbo_Z_Ferien.ZFE_LPE_ID
INNER JOIN dbo_Z_ERFASSUNG ON dbo_A_PERSONAL.LPE_ID = dbo_Z_ERFASSUNG.ZER_LPE
WHERE dbo_A_PERSONAL.LPE_ID=804 AND dbo_Z_ERFASSUNG.ZER_EIGENSCH = 3;
I need that so I can sum up the value I need from Z_ERFASSUNG and Z_Ferien but I don't know how to make it so each value is only "printed" once.
I hope I explained it well enough so you guys can help me out.
If I understand correctly an aggerate function is what you need here.
I added a sum function of both dbo_Z_Ferien & dbo_Z_ERFASSUNG, as well as adding a group by statement for LPE_ID. Which tells SQL to partition the sum only on LPE_ID
SELECT dbo_A_PERSONAL.LPE_ID, sum(dbo_Z_Ferien.ZFE_TAGE), sum(dbo_Z_ERFASSUNG.ZER_Std100)
FROM dbo_A_PERSONAL
INNER JOIN dbo_Z_Ferien ON dbo_A_PERSONAL.LPE_ID = dbo_Z_Ferien.ZFE_LPE_ID
INNER JOIN dbo_Z_ERFASSUNG ON dbo_A_PERSONAL.LPE_ID = dbo_Z_ERFASSUNG.ZER_LPE
WHERE dbo_A_PERSONAL.LPE_ID=804 AND dbo_Z_ERFASSUNG.ZER_EIGENSCH = 3
GROUP BY dbo_A_PERSONAL

Find 'Most Similar' Items in Table by Foreign Key

I have a child table with a number of charact/value pairs for a given 'material' (MaterialID). Any material can have a number of charact values and may have several of the same name (see id's 2,3).
The table has a large number of records (8+ million). What I'm trying to do is find the materials that are the most similar to a supplied material. That is, when I supply a MaterialID, I would like an ordered list of the most similar other materials (those with the most matching charact/value pairs).
I've done some research but, I may be missing some key terms or just not conceptualizing the problem correctly.
Any hints as to how to go about this would be very much appreciated.
ID MaterialID Charact Value
1 1 ROT_DIR CCW
2 1 SPECIAL_FEATURE CATALOG_CP
3 1 SPECIAL_FEATURE CHROME
4 1 SCHEDULE 80
5 2 BEARING_TYPE SB
6 2 SCHEDULE 80
7 3 ROT_DIR CCW
8 3 SPECIAL_FEATURE CATALOG_HSB
9 3 BEARING_TYPE SP
10 4 NDE_STYLE W_FAN
11 4 BEARING_TYPE SB
12 4 ROT_DIR CW*
You can do this with a self join:
select t.materialid, count(*) as nummatches
from t join
t tmat
on t.Charact = tmat.Charact and t.value = tmat.value
where tmat.materialid = #MaterialId
group by t.materialid
order by nummatches desc;
Notes:
You might want to remove the specified material, by adding where t.MaterialId <> tmat.MaterialId to the where clause.
If you want all materials, then make the join a left join and move the where condition to the on clause.
If you want only one material with the most matches, use select top 1.
If you want all materials with the most matches when there are ties, use `select top (1) with ties.

Generalize a query that involves multiple instances of three tables SQL

I am doing a formula to make some statistics in SQL, but I do not know how to improve a query I am working on...
I made a sqlfiddle so you can understand me better
So I have 3 tables and I need to solve a formula varying the indexes, i,j...
i j
---
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
and then do some sqrt and pow. I want the result in a table but I do not know how to generalize all those long queries into one...
This appears to just need a couple of CROSS JOINs:
SELECT ((N.n*M1.m)-(S1.s*S2.s)) /
(SQRT((N.n*M2.m)-(pow(S1.s,2))) * SQRT((N.n*M3.m)-(pow(S2.s,2))))
FROM N
CROSS JOIN sums as S1
CROSS JOIN sums as S2
JOIN mults as M1
ON M1.i = S1.i
AND M1.j = S2.i
JOIN mults as M2
ON M2.i = S1.i
AND M2.j = S1.i
JOIN mults as M3
ON M3.i = S2.i
AND M3.j = S2.i;
(I've modified the Fiddle to include this. Thanks for providing one!).
However, your overall design is a little suspicious to me; what exactly are you attempting to accomplish?

Why does this query return "incorrect" results?

I have 3 tables:
'CouponType' table:
AutoID Code Name
1 CouT001 SunCoupon
2 CouT002 GdFriCoupon
3 CouT003 1for1Coupon
'CouponIssued' table:
AutoID CouponNo CouponType_AutoID
1 Co001 1
2 Co002 1
3 Co003 1
4 Co004 2
5 Co005 2
6 Co006 2
'CouponUsed' table:
AutoID Coupon_AutoID
1 2
2 3
3 5
I am trying to join 3 tables together using this query below but apparently I am not getting right values for CouponIssued column:
select CouponType.AutoID, Code, Name, Count(CouponIssued.CouponType_AutoID), count(CouponUsed.Coupon_AutoID)
from (CouponType left join CouponIssued
on (CouponType.AutoID = CouponIssued.CouponType_AutoID))
left join CouponUsed
on (couponUsed.Coupon_AutoID = CouponIssued.AutoID)
group by CouponType.AutoID, code, name
order by code
The expected result should be like:
**Auto ID Code Name Issued used**
1 CouT001 SunCoupon 3 2
2 CouT002 GdFriCoupon 3 1
3 CouT003 1for1Coupon 0 0
Thanks!
SELECT t.AutoID
,t.Code
,t.Name
,count(i.CouponType_AutoID) AS issued
,count(u.Coupon_AutoID) AS used
FROM CouponType t
LEFT JOIN CouponIssued i ON i.CouponType_AutoID = t.AutoID
LEFT JOIN CouponUsed u ON u.Coupon_AutoID = i.AutoID
GROUP BY 1,2,3;
You might consider using less confusing names for your table columns. I have made very good experiences with using the same name for the same data across tables (as far as sensible).
In your example, AutoID is used for three different columns, two of which appear a second time in another table under a different name. This would still make sense if Coupon_AutoID was named CouponIssued_AutoID instead.
change count(Coupon.CouponType_AutoID) to count(CouponIssued.CouponType_AutoID) and count(Coupon.Coupon_AutoID) to count(CouponUsed.Coupon_AutoID)

Problem with SQL Join

I have two tables, tblEntities and tblScheduling.
tblEntities:
EntityID ShortName Active
1 Dirtville 1
2 Goldtown 1
3 Blackston 0
4 Cornfelt 1
5 Vick 1
tblScheduling:
ScheduleID EntityID SchedulingYearID
1 1 20
2 1 21
3 2 20
4 3 19
5 5 20
I need a query that will show ALL ACTIVE Entities and their schedule information for a particular ScheduleYearID.
Output should look like (the desired SchedulingYearID in this case is 20):
EntityID ScheduleID
1 1
2 3
4 NULL
5 5
The query that I have written so far is:
SELECT tblEntities.EntityID, tblEntities.ShortName, tblScheduling.ScheduleID
FROM tblScheduling RIGHT OUTER JOIN
tblEntities ON tblScheduling.EntityID = tblEntities.EntityID
WHERE (tblScheduling.SchedulingYearID = #SchedulingYearID)
AND (tblEntities.Active = 1)
ORDER BY tblEntities.EntityID
My problem is that using this query it will not include active entities without schedule information (such as EntityID 4 in the example above). I can write the query to display all active entities and their schedule status fine, but once I start limiting it via the SchedulingYearID I lose those particular entities.
Are there any solutions that I am obviously missing without having to resort to subqueries, cursors, etc.? If not it's not a big deal, I just feel like I am missing something simple here.
Try this... Join conditions are evaluated to produce the intermediate Join result set, and then, (for an outer join), all the rows from the "Outer" side are added back in before moving on... Where conditions are evaluated after all joins are done...
SELECT E.EntityID, E.ShortName, S.ScheduleID
FROM tblEntities E
Left Join tblScheduling S
ON S.EntityID = E.EntityID
And S.SchedulingYearID = #SchedulingYearID
WHERE E.Active = 1
ORDER BY E.EntityID
I change your join order cause I prefer left joins... but it doesn't matter
It's your conditions in the where clause:
(tblScheduling.SchedulingYearID = #SchedulingYearID)
when there is no tblScheduling info this wil always fail. Add
(((tblScheduling.SchedulingYearID = #SchedulingYearID) OR (tblScheduling.SchedulingYearID is null) )
or wathever null condition checking your DB uses.
I think the trouble is that the WHERE clause is filtering out the rows where SchedulingYearID is null. So don't.
SELECT tblEntities.EntityID, tblEntities.ShortName, tblScheduling.ScheduleID
FROM tblScheduling RIGHT OUTER JOIN
tblEntities ON tblScheduling.EntityID = tblEntities.EntityID
WHERE (tblScheduling.SchedulingYearID = #SchedulingYearID OR
tblScheduling.SchedulingYearID IS NULL)
AND (tblEntities.Active = 1)
ORDER BY tblEntities.EntityID;