Trying to use table aliases in SQL - sql

I'm a graphic designer trying my best to understand table aliases, but it's not working.
Here's what I have so far:
SELECT colours.colourid AS colourid1,
combinations.manufacturercolourid AS colourmanid1,
colours.colourname AS colourname1,
colours.colourhex AS colourhex1,
combinations.qecolourid2 AS colouridqe2,
colours.colourid AS colourid2,
colours.colourname AS colourname2,
colours.colourhex AS colourhex2,
colours.colourid AS colourid3,
combinations.qecolourid3 AS colouridqe3,
colours.colourname AS colourname3,
colours.colourhex AS colourhex3,
colours.colourid AS colourid4,
combinations.qecolourid4 AS colouridqe4,
colours.colourname AS colourname4,
colours.colourhex AS colourhex4,
combinations.coloursupplierid
FROM combinations
INNER JOIN colours
ON colours.colourid = combinations.manufacturercolourid;
Now, the idea is that in the colours lookup table, the id will pull the colour code, hex and name from the lookup table so that I can pull the colour code, hex and name for the 4 colours that I'm looking for. I can get this to work, but it only pulls up the first name, code and hex and I'm just not seeing what I'm doing wrong.

Your problem is that you are linking in only a single record from the colours table because you only have a single JOIN in your SQL. That record will match the color specified by manufacturer_colour_id.
You may also have a further problem in that your combinations table does not appear to be in proper normal form (although I could be wrong, not knowing the actual nature of the data you're trying to represent).
If I understand your problem correctly, the solution (using your current table structures) will be something more like:
SELECT C1.colourid AS colourid1,
CMB.manufacturercolourid AS colourmanid1,
C1.colourname AS colourname1,
C1.colourhex AS colourhex1,
CMB.qecolourid2 AS colouridqe2,
C2.colourid AS colourid2,
C2.colourname AS colourname2,
C2.colourhex AS colourhex2,
C3.colourid AS colourid3,
CMB.qecolourid3 AS colouridqe3,
C3.colourname AS colourname3,
C3.colourhex AS colourhex3,
C4.colourid AS colourid4,
CMB.qecolourid4 AS colouridqe4,
C4.colourname AS colourname4,
C4.colourhex AS colourhex4,
CMB.coloursupplierid
FROM combinations CMB
LEFT OUTER JOIN colours C1
ON C1.colourid = CMB.manufacturercolourid
LEFT OUTER JOIN colours C2
ON C2.colourid = CMB.qecolourid2
LEFT OUTER JOIN colours C3
ON C3.colourid = CMB.qecolourid3
LEFT OUTER JOIN colours C4
ON C4.colourid = CMB.qecolourid4
What's happening here is that I'm linking the colours table four times, once for each of the colour_id fields in the combinations table. To do so, I need to alias the table name each time so that I know which of the four possible instances of colours to use in the list of returned columns. Also, I'm using OUTER JOINs in the event that one or more colour_id columns might be empty. If that happened with INNER JOINs, the entire row would drop out of the result set.

You can use table aliases to reduce the amount of typing needed - by adding something like this:
SELECT
cl.colourid AS colourid1,
cb.manufacturercolourid AS colourmanid1,
cl.colourname AS colourname1,
... and so on.....
FROM
combinations AS cb
INNER JOIN
colours AS cl ON cl.colourid = cb.manufacturercolourid;
By defining a table alias cb for your table combinations, you can use that shorter alias in your SELECT and other parts of your statement, instead of having to always spell out the entire table name.
But your problem really is in the JOIN - you're only joining once, yet you expect to get four results back....
What you need to do is something like this:
SELECT
col1.colourid AS colourid1,
cb.manufacturercolourid AS colourmanid1,
col1.colourname AS colourname1,
col1.colourhex AS colourhex1,
cb.qecolourid2 AS colouridqe2,
col2.colourid AS colourid2,
col2.colourname AS colourname2,
col2.colourhex AS colourhex2,
col2.colourid AS colourid3,
cb.qecolourid3 AS colouridqe3,
col3.colourname AS colourname3,
col3.colourhex AS colourhex3,
col3.colourid AS colourid4,
cb.qecolourid4 AS colouridqe4,
col4.colourname AS colourname4,
col4.colourhex AS colourhex4,
cb.coloursupplierid
FROM
combinations cb
INNER JOIN colours AS col1 ON col1.colourid = cb.manufacturercolourid
INNER JOIN colours AS col2 ON col2.colourid = cb.qecolourid2
INNER JOIN colours AS col3 ON col3.colourid = cb.qecolourid3
INNER JOIN colours AS col4 ON col4.colourid = cb.qecolourid4

This is not an exhaustive answer, but your problem has to do with your how you are using the JOINs. Table and column aliases do not affect the output result set.
You are selecting the same field names four times, and that is why you are getting strange results.

These are all great, but for some reason when I try to use them, I get an error in the page:
[Microsoft][ODBC Microsoft Access Driver] Syntax error (missing operator) in query expression
I think I understand how to use the table aliases now, but for some reason, even though I'm sure it should work, the page doesn't like it.

Related

Finding differences in queries using two criteria

I'm trying to find a way to find a way to compare two queries that use a combine sent of criteria. In this case we have Prefixes (Two letter code like DA) and Pack number 1234567. In the query I've created a field that combines these two things so it appears 1234567DA this is done with each of the queries from the separate tables they are pulled from. The idea is that if this is in one table and not the other it would show up as "False". I tried to use an Unmatched query but that doesn't seem to work. What I have currently is as follows:
SELECT
[1LagoTest].Prefix,
[1BigPicPackPref].BigPicPP,
IIf([BigPicPP]=[LagoPP],"True","False") AS Compare,
[1LagoTest].RETAIL,
[1LagoTest].MEDIA
FROM 1LagoTest
LEFT JOIN 1BigPicPackPref
ON [1LagoTest].[Prefix] = [1BigPicPackPref].[BigPicPP]
WHERE (((IIf([BigPicPP]=[LagoPP],"True","False")) Like "False")
AND (([1LagoTest].MEDIA) Not Like "*2019 FL*"))
ORDER BY [1LagoTest].RETAIL;
Right now it will show whats missing from LagoPP but doesn't give me anything from missing packs in BigPicPP. Any help in the right direction would be greatly appreciated.
Thanks!!
This gets a little tricky in Access without FULL OUTER JOIN, but the general idea to is replicate a FULL OUTER JOIN using UNION ALL, then filter from that.
Something like this:
SELECT I.Prefix,
I.BigPicPP,
I.Compare,
I.Retail,
I.Media
FROM (SELECT L.Prefix,
B.BigPicPP,
IIf([BigPicPP]=[LagoPP],"True","False") as Compare,
L.Retail,
L.Media
FROM 1LagoTest L
JOIN 1BigPicPackPref B ON L.Prefix = B.BigPicPP
WHERE L.Media NOT LIKE "*2019 FL*"
UNION ALL
SELECT L.Prefix,
B.BigPicPP,
"False", --Missing records from 1BigPicPackPref
L.Retail,
L.Media
FROM 1LagoTest L
LEFT JOIN 1BigPicPackPref B ON L.Prefix = B.BigPicPP
AND L.Media NOT LIKE "*2019 FL*"
WHERE B.Prefix IS NULL
UNION ALL
SELECT B.Prefix,
B.BigPicPP,
"False", --Missing records from 1LagoTest
L.Retail,
L.Media
FROM 1LagoTest L
RIGHT JOIN 1BigPicPackPref B ON L.Prefix = B.BigPicPP
AND L.Media NOT LIKE "*2019 FL*"
WHERE L.Prefix IS NULL
) AS I
You only need IFF in the first part of the union because in the second two parts one side will always be NULL, so we know the compare will always fail and be False.
You shouldn't need this part of your current WHERE clause at all (((IIf([BigPicPP]=[LagoPP],"True","False")) Like "False"). But if you only want to see False records, just add WHERE I.Compare = "False" to the bottom of the outer select.
The reason the "Unmatched" query (assuming through the Wizard) does not work, is because you are attempting to see the values of two separate tables / queries that do not match either table / query. This is not how the "Unmatched" works. All that will give you is a single table / query that does not match another single table / query.
This can most likely be done any number of ways, but this would probably get you where you want to be (or close to it):
SELECT
a.Prefix,
b.BigPicPP,
IIf([BigPicPP]=[LagoPP],"True","False") AS Compare,
a.RETAIL,
a.MEDIA
FROM [1LagoTest] a
LEFT JOIN [1BigPicPackPref] b ON a.Prefix = b.BigPicPP
WHERE a.MEDIA Not Like "*2019 FL*"
AND b.BigPicPP IS NULL
ORDER BY a.RETAIL
UNION
SELECT
a.Prefix,
b.BigPicPP,
IIf([BigPicPP]=[LagoPP],"True","False") AS Compare,
a.RETAIL,
a.MEDIA
FROM [1LagoTest] a
RIGHT JOIN [1BigPicPackPref] b ON a.Prefix = b.BigPicPP
WHERE a.MEDIA Not Like "*2019 FL*"
AND a.Prefix IS NULL
ORDER BY a.RETAIL
NOTE: Depending on the data structure, the ORDER BY may cause some issues.
So the way I got this to finally work was to build two separate queries. One looking at what was missing from Lago and One that was looking at what was missing from BigPic. It was the only way I could get it to give me both sets of missing data. If I can find a better way to do it through one query I will report back as I'm still gonna play around with it.

Access SQL query without duplicate results

I made a query and wanted to not have any duplicates but i got some times 3 duplicates and when i used DISTINCT or DISTINCTROW i got only 2 duplicates.
SELECT f.flight_code,
f.status,
a.airport_name,
a1.airport_name,
f.departing_date+f.departing_time AS SupposedDepartingTime,
f.landing_date+f.landing_time AS SupposedLandingTime,
de.actual_takeoff_date+de.actual_takeoff_time AS ActualDepartingTime,
SupposedLandingTime+(ActualDepartingTime-SupposedDepartingTime) AS ActualLandingTime
FROM
(((Flights AS f
LEFT JOIN Aireports AS a
ON a.airport_code = f.depart_ap)
LEFT JOIN Aireports AS a1
ON f.target_ap = a1.airport_code)
LEFT JOIN Irregular_Events AS ie
ON f.flight_code = ie.flight_code)
LEFT JOIN Delay_Event AS de
ON ie.IE_code = de.delay_code;
had to use LEFT JOIN because when i used INNER JOIN i missed some of the things i wanted to show because i wanted to see all the flights and not only the flights that got delayed or canceled.
This is the results when i used INNER JOIN, you can see only the flights that have the status "ביטול" or "עיכוב" and that is not what i wanted.
[the results with LEFT JOIN][2]
[2]: https://i.stack.imgur.com/cgE2G.png
and when i used DISTINCT where you see the rows with the NUMBER 6 on the first column it appear only two times
IMPORTANT!
I just checked my query and all the tables i use there and i saw my problem but dont know how to fix it!
in the table Irregular_Events i have more the one event for flights 3,6 and 8 and that is why when i use LEFT JOIN i see more even thou i use distinct, please give me some help!
Not entirely sure without seeing the table structure, but this might work:
SELECT f.flight_code,
f.status,
a.airport_name,
a1.airport_name,
f.departing_date+f.departing_time AS SupposedDepartingTime,
f.landing_date+f.landing_time AS SupposedLandingTime,
de.actual_takeoff_date+de.actual_takeoff_time AS ActualDepartingTime,
SupposedLandingTime+(ActualDepartingTime-SupposedDepartingTime) AS ActualLandingTime
FROM
((Flights AS f
LEFT JOIN Aireports AS a
ON a.airport_code = f.depart_ap)
LEFT JOIN Aireports AS a1
ON f.target_ap = a1.airport_code)
LEFT JOIN
(
SELECT
ie.flight_code,
de1.actual_takeoff_date,
de1.actual_takeoff_time
FROM
Irregular_Events ie
INNER JOIN Event AS de1
ON ie.IE_code = de1.delay_code
) AS de
ON f.flight_code = de.flight_code
It is hard to tell what is the problem with your query without any sample of the output, and without any description of the structure of your tables.
But your problem is that your are querying from the flights table, which [I assume] can be linked to multiple irregular_events, which can possibly also be linked to multiple delay_event.
If you want to get only one row per flight, you need to make sure your joins return only one row too. Maybe you can do it by adding one more condition to the join, or by adding a condition in a sub-query.
EDIT
You could try to add a GROUP BY to the query:
GROUP BY
f.flight_code,
f.status,
a.airport_name,
a1.airport_name;

Long Text Field over 255 Characters gets truncated

Not sure why my field in my query is getting truncated upon the return of the result. The value is being stored in the field, but gets truncated by access to help with "performance". I have reviewed multiple forums and SO posts to no avail.
Problems listed at link do not apply, Aggregation, Uniqueness, Union, Format Property, Row Source
What is wrong with my query? Instructions field in the Customer table is the one that is getting truncated.
Here is the raw query generated by access:
SELECT Task.ID, Task.TaskID, Task.TaskName, Task.TypeID, TaskType.TaskTypeName, Task.CustomerID, Customer.CustomerName, Customer.OnHold, Customer.Blacklisted, Customer.CustomerEngagementRecieved, Customer.AutoEmail, Customer.SpecialInstructions, Customer.Instructions, Task.QuoteRequired, Task.PriorityID, Priority.Priority, Task.Min, Task.Max, Task.Projected, Task.DeadlineDate, Task.ResourceID, Resource.ResourceName, Resource.Email, Resource.Extension, Task.Description, Task.StatusID, Status.Status, Task.DeveloperLog, Task.TaskPOCID, POC.Phone, POC.Email, Task.OtherPOC, Task.OtherPOCPhone, Task.OtherPOCEmail, Task.FolderPath, Task.StopBilling, Task.Premium, Task.EntryDate, Task.CompleteDate, Task.AssignedBy, Task.SettingsID, Settings.AutoEmail
FROM TaskType
INNER JOIN (Status
INNER JOIN (Settings
INNER JOIN (Resource
INNER JOIN (Priority
INNER JOIN (Customer
INNER JOIN (Task
INNER JOIN POC ON Task.TaskPOCID = POC.POCID)
ON Customer.CustID = Task.CustomerID)
ON Priority.PriorityID = Task.PriorityID)
ON Resource.ResourceID = Task.ResourceID)
ON Settings.SettingsID = Task.SettingsID)
ON Status.StatusID = Task.StatusID)
ON TaskType.TTID = Task.TypeID;
`
Have a close read of this - http://allenbrowne.com/ser-63.html something in your set up will causing the truncation.
If it's when you cut and paste the query results that can also be mis-leading. When you say a Long Text are these linked tables?
I'd also rename your Min and Max fields as they are reserved words and may cause access to think you are aggregating your data.
So from the sounds of it, Access just sometimes will ALWAYS truncate the field no matter what the settings. There is a way to force access to show the entire field though, by using the DLOOKUP() function instead of using a Control Source.
Here is the Answer to my current Issue for reference,
=DLOOKUP("Instructions", "Customer", "CustID=" & [CustomerID])

Way to combine filtered results using LIKE

I have a many to many relationship between people and some electronic codes. The table with the codes has the code itself, and a text description of the code. A typical result set from a query might be (there are many codes that contain "broken" so I feel like it's better to search the text description rather than add a bunch of ORs for every code.)
id# text of code
1234 broken laptop
1234 broken mouse
Currently the best way for me to get a result set like this is to use the LIKE%broken% filter. Without changing the text description, is there any way I can return only one instance of a code with broken? So in the example above the query would only return 1234 and broken mouse OR broken laptop. In this scenario it doesn't matter which is returned, all I'm looking for is the presence of "broken" in any of the text descriptions of that person's codes.
My solution at the moment is to create a view that would return
`id# text of code
1234 broken laptop
1234 broken mouse`
and using SELECT DISTINCT ID# while querying the view to get only one instance of each.
EDIT ACTUALLY QUERY
SELECT tblVisits.kha_id, tblICD.descrip, min(tblICD.Descrip) as expr1
FROM tblVisits inner join
icd_jxn on tblVisits.kha_id = icd_jxn.kha)id inner join tblICD.icd_fk=tblICD.ICD_ID
group by tblVisits.kha_id, tblicd.descrip
having (tblICD.descrip like n'%broken%')
You could use the below query to SELECT the MIN code. This will ensure only text per id.
SELECT t.id, MIN(t.textofcode) as textofcode
FROM table t
WHERE t.textofcode LIKE '%broken%'
GROUP BY t.id
Updated Actual Query:
SELECT tblVisits.kha_id,
MIN(tblICD.Descrip)
FROM tblVisits
INNER JOIN icd_jxn ON tblVisits.kha_id = icd_jxn.kha)id
INNER JOIN tblicd ON icd_jxn.icd_fk = tbl.icd_id
WHERE tblICD.descrip like n'%broken%'
GROUP BY tblVisits.kha_id

Why do I have to use DISTINCT for this to work?

here's my problem: I have an SQL query that makes 4 calls to a lookup table to return their values from a list of combinations in another table. I finally got this working, and for some reason, when I run the query without DISTINCT, I get a ton of data back, so I'm guessing that I'm either missing something or not doing this correctly. It would be really great if this would not only work, but also return the list alphabetically by the first colour name.
I'm putting my SQL here I hope I've explained this well enough:
SELECT DISTINCT
colour1.ColourID AS colour1_ColourID,
colour1.ColourName AS colour1_ColourName,
colour1.ColourHex AS colour1_ColourHex,
colour1.ManufacturerColourID AS colour1_ManufacturerColourID,
colour2.ColourID AS colour2_ColourID,
colour2.ColourName AS colour2_ColourName,
colour2.ColourHex AS colour2_ColourHex,
colour2.QEColourID2 AS colour2_QEColourID2,
colour3.ColourID AS colour3_ColourID,
colour3.ColourName AS colour3_ColourName,
colour3.ColourHex AS colour3_ColourHex,
colour3.QEColourID3 AS colour3_QEColourID3,
colour4.ColourID AS colour4_ColourID,
colour4.ColourName AS colour4_ColourName,
colour4.ColourHex AS colour4_ColourHex,
colour4.QEColourID4 AS colour4_QEColourID4,
Combinations.ID,
Combinations.ManufacturerColourID AS Combinations_ManufacturerColourID,
Combinations.QEColourID2 AS Combinations_QEColourID2,
Combinations.QEColourID3 AS Combinations_QEColourID3,
Combinations.QEColourID4 AS Combinations_QEColourID4,
Combinations.ColourSupplierID,
ColourSuppliers.ColourSupplier
FROM
ColourSuppliers INNER JOIN
(
colour4 INNER JOIN
(
colour3 INNER JOIN
(
colour2 INNER JOIN
(
colour1 INNER JOIN Combinations ON
colour1.ColourID=Combinations.ManufacturerColourID
) ON colour2.ColourID=Combinations.QEColourID2
) ON colour3.ColourID=Combinations.QEColourID3
) ON colour4.ColourID=Combinations.QEColourID4
) ON ColourSuppliers.ColourSupplierID=Combinations.ColourSupplierID
WHERE Combinations.ColourSupplierID = ?
Thanks
Steph
It looks as though you've probably got multiple records for each set of four colour combinations in the Combinations table - posting the structure of the table might help us to work it out.
Adding the clause order by colour1.ColourName to the end of the query should sort it alphabetically by the first colour name.
My guess (and it is a guess because your SQL query is very wide!) is that you're getting the cartesian product.