?? Combine, join, insert in query Access 2007-2010? - sql

I have two tables that I would like to make into one table.
TABLE WASP_COLOR1
ID NAME COLOR CODE
1 WASP01 RED RD
2 WASP04 RED RD
3 WASP19 BLUE BL
TABLE WASP_COLOR2
ID NAME SIZE CODE
1 WASP01 6 RD
2 WASP13 10 BL
3 WASP22 4 BL
I'm a novice and I need clear direction on how to obtain these results. (I want the duplicates merged.)
TABLE WASP_COLOR1
ID NAME COLOR SIZE CODE
1 WASP01 RED 6 RD
2 WASP04 RED RD
3 WASP19 BLUE BL
4 WASP13 10 BL
5 WASP22 4 BL
I tried the following:
SELECT
distinct wasp_color2.name, wasp_color2.size,
wasp_color2.code, wasp_color1.name, wasp_color1.color,
wasp_color1.code
INTO
wasp_color1
FROM
wasp_color2, wasp_color1;
Received error
I tried:
SELECT
distinct wasp_color2.name, wasp_color2.size, wasp_color2.code,
wasp_color1.name, wasp_color1.color, wasp_color1.code
INTO
test
FROM
wasp_color2, wasp_color1;
Received 9 rows instead of 5
I tried:
SELECT
name.wasp_color1, name.wasp_color2, color, size,
code.wasp_color1, code.wasp_color2
INTO
test
FROM wasp_color2, wasp_color1;
This asks for a parameter value, which is a manual entry and cumbersome
I tried:
SELECT
coalesce name.wasp_color1, name.wasp_color2, color,
size, code.wasp_color1, code.wasp_color2
INTO
test
FROM
wasp_color2, wasp_color1 full join;
Received error

Perhaps something like this as MS access doesn't support full outer joins.
What this does is generate two data sets one for wasp_Color1 and those records that match in wasp_Color2 and vice-versa. and then combine's those results into one data set eliminating the duplicates.
For a better understanding of joins: see https://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
Select WC1.Name, WC1.Color, WC2.Size, WC1.Code
FROM wasp_Color1 wc1
LEFT JOIN wasp_color2 wc2
on wc1.Name = WC2.Name
and wc1.code = wc2.code
UNION
Select WC2.Name, WC1.Color, WC2.Size, WC2.Code
FROM wasp_Color1 wc1
RIGHT JOIN wasp_color2 wc2
on wc1.Name = WC2.Name
and wc1.code = wc2.code

Related

MS access join two tables, get unique rows

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
)

SQL Server: Two COUNTs in one query multiplying with one another in output

I have a query is used to display information in a queue and part of that information is showing the amount of child entities (packages and labs) that belong to the parent entity (change). However instead of showing the individual counts of each type of child, they multiply with one another.
In the below case, there are supposed to be 3 labs and 18 packages, however the the multiply with one another and the output is 54 of each.
Below is the offending portion of the query.
SELECT cef.ChangeId, COUNT(pac.PackageId) AS 'Packages', COUNT(lab.LabRequestId) AS 'Labs'
FROM dbo.ChangeEvaluationForm cef
LEFT JOIN dbo.Lab
ON cef.ChangeId = Lab.ChangeId
LEFT JOIN dbo.Package pac
ON (cef.ChangeId = pac.ChangeId AND pac.PackageStatus != 6 AND pac.PackageStatus !=7)
WHERE cef.ChangeId = 255
GROUP BY cef.ChangeId
I feel like this is obvious but it's not occurring to me how to fix it so the two counts are independent of one another like to me they should be. There doesn't seem to be a scenario like this in any of my research either. Can anyone guide me in the right direction?
Because you do multiply source rows by each left join. So sometimes you have more likely cross join here.
SELECT cef.ChangeId, p.Packages, l.Labs
FROM dbo.ChangeEvaluationForm cef
OUTER APPLY(
SELECT COUNT(*) as Labs
FROM dbo.Lab
WHERE cef.ChangeId = Lab.ChangeId
) l
OUTER APPLY(
SELECT COUNT(*) AS Packages
FROM dbo.Package pac
WHERE (cef.ChangeId = pac.ChangeId AND pac.PackageStatus != 6 AND pac.PackageStatus !=7)
) p
WHERE cef.ChangeId = 255
GROUP BY cef.ChangeId
perhaps GROUP BY is not needed now.
From you question its difficult to derive what result do you expect from your query. So I presume you want following result:
+----------+----------+------+
| ChangeId | Packages | Labs |
+----------+----------+------+
| 255 | 18 | 3 |
+----------+----------+------+
Try below query if you are looking for above mentioned result.
SELECT cef.ChangeId, ISNULL(pac.PacCount, 0) AS 'Packages', ISNULL(Lab.LabCount, 0) AS 'Labs'
FROM dbo.ChangeEvaluationForm cef
LEFT JOIN (SELECT Lab.ChangeId, COUNT(*) LabCount FROM dbo.Lab GROUP BY) Lab
ON cef.ChangeId = Lab.ChangeId
LEFT JOIN (SELECT pac.ChangeId, COUNT(*) PacCount FROM dbo.Package pac WHERE pac.PackageStatus != 6 AND pac.PackageStatus !=7 GROUP BY pac.ChangeId) pac
ON cef.ChangeId = pac.ChangeId
WHERE cef.ChangeId = 255
Query Explanation:
In your query you didn't use group by, so it ended up giving you 54 as count which is Cartesian product.
In this query I tried to group by 'ChangeId' and find aggregate before joining tables. So 3 labs and 18 packages will be counted before join.
Your will also notice that I have moved PackageStatus filter before group by in pac table. So unwanted record won't mess with our count.
You start with a particular ChangeId from the dbo.ChangeEvaluationForm table (ChangeId = 255 from your example), then join to the dbo.Lab table. This join makes your result go from 1 row to 3, considering there are 3 Labs with ChangeId = 255. Your problem is on the next join, you are joining all 3 resulting rows from the previous join with the dbo.Package table, which has 18 rows for ChangeId = 255. The resulting count for columns pac.PackageId and lab.LabRequestId will then be 3 x 18 = 54.
To get what you want, there are 2 easy solutions:
Use COUNT DISTINCT instead of COUNT. This will just count the different values of pac.PackageId and lab.LabRequestId and not the repeated ones.
Split the joins into 2 subqueries and join their result (by ChangeId)

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.

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;