Ms Access Delete Query with Join and Where Clause - sql

I have 2 tables (tblTrainingElements and tblCourses).
tblTrainingElements has the following fields:
([Training Element ID], [Course ID], [Title],[Duration (min)],[Patient],[Status],[Description], [Comments],[Site],[ElementSeq])
tblCourses has the following relevant fields:
[Course ID], [App ID]
I need to delete all records in tblTrainingElements WHERE the [App ID] from tblCourses = "CAD". I need to join the tables on the [Course ID] field. Below is the SQL statement that I tried to use. I keep getting the error message "Please specify which table you would like to delete from"
DELETE tblCourses.[Course Name], tblCourses.[App ID], tblTrainingElements.[Training Element ID], tblTrainingElements.[Course ID], tblTrainingElements.Title, tblTrainingElements.[Duration (min)], tblTrainingElements.Patient, tblTrainingElements.Status, tblTrainingElements.Description, tblTrainingElements.Comments, tblTrainingElements.Site, tblTrainingElements.ElementSeq
FROM tblCourses INNER JOIN tblTrainingElements ON tblCourses.[Course ID] = tblTrainingElements.[Course ID]
WHERE (((tblCourses.[App ID])="CAD"))

Delete records only in tblTrainingElements table:
DELETE *
FROM tblTrainingElements
WHERE tblTrainingElements.[Course ID] IN (SELECT tblCourses.[Course ID] FROM tblCourses WHERE tblCourses.[App ID]="CAD" );

DELETE tc
FROM tblCourses tc
INNER JOIN tblTrainingElements tte ON tc.[Course ID] = tte.[Course ID]
WHERE (((tc.[App ID])="CAD"))

Related

Error: The order by clause is invalid in views

I'm getting the following error in SQL Server 14 where I am trying to build a view based on 4 tables
The ORDER BY clause is invalid in views, inline functions, derived
tables, subqueries, and common table expressions, unless TOP, OFFSET
or FOR XML is also specified
How do I fix the below so I don't get this error?
SELECT dbo.PS_Proj.[Project ID],
case
when PS_Proj.[City Name] is not null then concat(PS_Proj.[City Name], ' ', PS_Proj.[State])
when PS_Billing.[Location] is not null then max(PS_Billing.[Location])
when PS_Time.[Labor Location ID] is not null then max(PS_Location.[Labor Location Name])
else null
end AS [Location]
FROM dbo.PS_Location RIGHT OUTER JOIN
dbo.PS_Time ON dbo.PS_Location.[Labor Location ID] = dbo.PS_Time.[Labor Location ID] RIGHT OUTER JOIN
dbo.PS_Proj ON dbo.PS_Time.[Project ID] = dbo.PS_Proj.[Project ID] LEFT OUTER JOIN
dbo.PS_Billing ON dbo.PS_Proj.[Project ID] = dbo.PS_Billing.[Project ID]
ORDER BY PS_Billing.[T/S Date], PS_Time.[Date]
I'd like for the most recent PS_Billing location to show and if that is null for the most recent PS_Time location to show.
Create your view without Order By. Remove ORDER BY PS_Billing.[T/S Date], PS_Time.[Date] And add them to your SELECT.
SELECT
PS_Billing.[T/S Date] AS TsDate,
PS_Time.[Date] AS Date,
dbo.PS_Proj.[Project ID],
case
when PS_Proj.[City Name] is not null then concat(PS_Proj.[City Name], ' ', PS_Proj.[State])
when PS_Billing.[Location] is not null then max(PS_Billing.[Location])
when PS_Time.[Labor Location ID] is not null then max(PS_Location.[Labor Location Name])
else null
end AS [Location]
FROM dbo.PS_Location RIGHT OUTER JOIN
dbo.PS_Time ON dbo.PS_Location.[Labor Location ID] = dbo.PS_Time.[Labor Location ID] RIGHT OUTER JOIN
dbo.PS_Proj ON dbo.PS_Time.[Project ID] = dbo.PS_Proj.[Project ID] LEFT OUTER JOIN
dbo.PS_Billing ON dbo.PS_Proj.[Project ID] = dbo.PS_Billing.[Project ID]
And select from your view with order by line
Select FROM YOUR_VIEW_NAME as V
Order By V.TsDate, V.Date
You have some aggregate data inside your case expression and you don't have a group by. I am making some guesses here. Also, you should get in the habit of using aliases, it makes things a lot simpler. I would also suggest not putting spaces in your column names as it forces you to constantly wrap columns in square brackets.
Something like this should get you close.
SELECT p.[Project ID]
, MAX(case
when p.[City Name] is not null then concat(p.[City Name], ' ', p.[State])
when b.[Location] is not null then b.[Location]
when t.[Labor Location ID] is not null then l.[Labor Location Name]
else null
end) AS [Location]
FROM dbo.PS_Location l
RIGHT OUTER JOIN dbo.PS_Time t ON l.[Labor Location ID] = t.[Labor Location ID]
RIGHT OUTER JOIN dbo.PS_Proj p ON t.[Project ID] = p.[Project ID]
LEFT OUTER JOIN dbo.PS_Billing b ON p.[Project ID] = b.[Project ID]
GROUP BY p.[Project ID]

3 Count functions returning the same value

So i have this query:
SELECT Posts.[Post ID], Count(Comments.[Comment ID]) AS [CountOfComment ID],
Count(Shares.[Share ID]) AS [CountOfShare ID],
Count(Likes.[Like ID]) AS [CountOfLike ID]
FROM ((Posts INNER JOIN Likes ON Posts.[Post ID] = Likes.[Post ID])
INNER JOIN Shares ON Posts.[Post ID] = Shares.[Post ID])
INNER JOIN Comments ON Posts.[Post ID] = Comments.[Post ID]
WHERE posts.[post id] = 5
GROUP BY Posts.[Post ID];
Which should return the results:
post.[post id]= 5
CountofcommentID= 4
CountofShareID = 5
CountofLikeID = 15
But instead i get post.[post id] = 5, and the rest =300.
I know that this is because it is counting up all the permutations of all the IDs, but how do i change that to get the results that i want?
You are misunderstanding what COUNT() does. It counts the number of non-NULL values. The proper solution is to use COUNT(DISTINCT). Because MS-Access does not support COUNT(DISTINCT) you might interpret that as "get a functional database".
Inside MS Access, you can do this using subqueries of some type. Here is one method:
SELECT p.[Post ID],
(SELECT COUNT(*)
FROM (SELECT DISTINCT [Post Id], [Comment ID]
FROM Comments as c
) as c
WHERE c.[Post Id] = p.[Post Id]
) as [CountOfComment ID],
(SELECT COUNT(*)
FROM (SELECT DISTINCT [Post Id], [Share ID]
FROM Shares as s
) as s
WHERE s.[Post Id] = p.[Post Id]
) as [CountOfShare ID],
(SELECT COUNT(*)
FROM (SELECT DISTINCT [Post Id], [Like ID]
FROM Likes as l
) as l
WHERE l.[Post Id] = p.[Post Id]
) as [CountOfLikes ID]
FROM Posts as p
WHERE p.[post id] = 5
GROUP BY p.[Post ID];
When you join, you get a row for every combination. Therefore, count does count every row, which has value different from null. So, what you want is to count DISTINCT ids. I.e.:
SELECT Posts.[Post ID], Count(DISTINCT Comments.[Comment ID]) AS [CountOfComment ID],
Count(DISTINCT Shares.[Share ID]) AS [CountOfShare ID],
Count(DISTINCT Likes.[Like ID]) AS [CountOfLike ID]
FROM ((Posts INNER JOIN Likes ON Posts.[Post ID] = Likes.[Post ID])
INNER JOIN Shares ON Posts.[Post ID] = Shares.[Post ID])
INNER JOIN Comments ON Posts.[Post ID] = Comments.[Post ID]
WHERE posts.[post id] = 5
GROUP BY Posts.[Post ID];
If the system does not support this syntax, you might need to do subqueries:
Select Posts.[Post ID],
(Select count([Share ID]) from Shares where Posts.[Post ID] = Shares.[Post ID]) as SharesCount
FROM Posts
WHERE posts.[post id] = 5;

Update a table according to subquery data

I have the following query that extracts unique records from a table:
SELECT First(t1.[Site Number]) AS [FirstOfSite Number], t1.[Customer Number], First(t1.Address1) AS FirstOfAddress1
FROM tblImport1 AS t1
GROUP BY t1.[Customer Number]
ORDER BY t1.[Customer Number];
I want to update a second table, say tblimport, according to the query above by linking the fields t1.[Site Number] withtblimport.[Site Number].
I made the following query:
UPDATE tblimport
INNER JOIN tblimport on [tblimport].[site number]=[t1].[site number]
(SELECT First(t1.[Site Number]) AS [FirstOfSite Number], t1.[Customer Number], First(t1.Address1) AS FirstOfAddress1
FROM tblImport1 AS t1
GROUP BY t1.[Customer Number])
set tblimport.address1=t1.address1
However I get syntax error. Where am I going wrong here?
EDIT
I read the article suggested and I have amended the query this way:
UPDATE D
set D.address1=t1.address1
FROM tblimport as D
INNER JOIN (SELECT First(t1.[Site Number]) AS [FirstOfSite Number], t1.[Customer Number], First(t1.Address1) AS FirstOfAddress1 FROM tblImport1 AS t1 GROUP BY t1.[Customer Number])
ON t1.[Site Number]=D.[Site Number]
But I still have the syntax error.

SQL joins and group by with 3 separate tables

I have two separate queries here that I need to make into one query, I'll post the queries, then try to explain what I'm trying to do.
SELECT Distinct I.ITMCDE, V.VNDRCDE, V.VNAME
FROM (SELECT RIGHT(Items.[Item Number], 3) as ITMCDE FROM Items) I,
(SELECT LEFT(Vendors.[Vendor ID], 3) as VNDRCDE,
Vendors.[Vendor Name] as VNAME
FROM Vendors) V
WHERE I.ITMCDE = V.VNDRCDE
In this first one, I simply match up the vendor code with the item code, to get the vendor name that produces the item.
SELECT DISTINCT (Items.[Item Description]), ItemQuantities.[QTY Available],
Items.[Selling U Of M], Items.[Item Number]
FROM ItemQuantities
INNER JOIN Items ON ItemQuantities.[Item Number] = Items.[Item Number]
WHERE Items.[Item Number] LIKE 'WH%'
AND Items.[Item Number] NOT LIKE '%RMW'
In this second one I'm selecting the item description, quantity available from two separate tables (quantity available is in a different table, match them up using the item number)
As you can see, the only correlation between the three tables is the item number, and not even that in the vendors table. The last three characters of the item number correlate with the first three characters of the vendor id... I did not design this setup. I'm just trying to work with it now.
How do I join these two statements into one single statement that will give me the vendor name, item description, Unit of Measure (Selling U of M), and item quantity where the item description is unique?
I think this should work:
SELECT DISTINCT Items.[Item Description],
ItemQuantities.[QTY Available],
Items.[Selling U Of M],
Items.[Item Number],
V.VNAME
FROM ItemQuantities
INNER JOIN Items ON ItemQuantities.[Item Number] = Items.[Item Number]
INNER JOIN Vendors ON
RIGHT(Items.[Item Number], 3) = LEFT(Vendors.[Vendor ID], 3)
WHERE Items.[Item Number] LIKE 'WH%'
AND Items.[Item Number] NOT LIKE '%RMW'
You can join it in:
SELECT DISTINCT (i.[Item Description]), iq.[QTY Available],
i.[Selling U Of M], i.[Item Number],
V.VNDRCDE, V.VNAME
FROM ItemQuantities iq INNER JOIN
Items i
ON iq.[Item Number] = i.[Item Number] left outer join
Vendors v
on LEFT(v.[Vendor ID], 3) = RIGHT(i.[Item Number], 3)
WHERE i.[Item Number] LIKE 'WH%' and
i.[Item Number] NOT LIKE '%RMW'
I am not sure if you intend anything special with the parentheses around i.[Item Description]. The distinct keyword applies to the entire row.
If you want distinct only on the description, then you need to use group by. Something like:
SELECT i.[Item Description],
max(iq.[QTY Available]),
max(i.[Selling U Of M]), max(i.[Item Number]),
max(V.VNDRCDE), max(V.VNAME)
FROM ItemQuantities iq INNER JOIN
Items i
ON iq.[Item Number] = i.[Item Number] left outer join
Vendors v
on LEFT(v.[Vendor ID], 3) = RIGHT(i.[Item Number], 3)
WHERE i.[Item Number] LIKE 'WH%' and
i.[Item Number] NOT LIKE '%RMW'
group by i.[Item Description])
The max() will return the maximum value. If all are the same, then this is a good way to get an "arbitrary" value.
#sgeddes Thank you.
This is what I came up with
SELECT DISTINCT
Item.ITEMNMBR AS [Item Number],
Item.ITEMDESC AS [Item Description],
Item.ITMGEDSC AS [Item Category],
Item.SELNGUOM AS [Unit of Measure],
(SELECT VENDNAME FROM PM00200 WHERE (VENDORID = IV00103.VENDORID)) AS [Vendor Name],
(CASE WHEN Quan.QTYONHND > 0 THEN 'In Stock' ELSE 'Out of Stock' END) AS [Stock Status]
FROM IV00101 AS Item INNER JOIN
IV00102 AS Quan ON Item.ITEMNMBR = Quan.ITEMNMBR INNER JOIN
IV00103 ON Item.ITEMNMBR = IV00103.ITEMNMBR AND Quan.ITEMNMBR = IV00103.ITEMNMBR
WHERE (Item.ITEMNMBR LIKE 'WH%') AND (IV00103.VENDORID NOT LIKE '%MIL')

If logic in SQL or Access queries

Greetings, fellow SO people.
I am working on a project that has me working with an Access database. Here's the setup:
I have three tables:
Tab1 with employee names, ID#s, Manager names and Manager ID#s.
Tab2 with chat info, employee ID#s and employee names.
Tab3 with Manager ID#s, Manager names and team names.
I currently have a query that selects the following:
tab2.[employee name], tab2.[employee id], tab3.[chat info], tab1.[manager id], tab1.[manager id], tab3.[team name]
where
tab2.[employee id] = tab1.[employee id] and tab2.[manager id] = tab3.[manager id];
What I am trying to accomplish is this: I would like to have a way to put "Unknown" in the "Team" field if the IDs don't match up somewhere along the line. Any ideas?
Thanks in advance!
Perhaps something like:
select tab2.[employee name],
tab2.[employee id],
tab3.[chat info],
tab1.[manager id],
Nz(tab3.[team name], 'Unknown') as [team name]
from (tab2
left join tab1
on tab2.[employee id] = tab1.[employee id])
left join tab3
on tab2.[manager id] = tab3.[manager id]
SELECT
tab2.[employee name], tab2.[employee id],
tab3.[chat info], tab1.[manager id],
tab1.[manager id],
Nz(tab3.[team name],"Unknown")
FROM (tab2
LEFT JOIN tab1
ON tab2.[employee id] = tab1.[employee id])
LEFT JOIN tab3
ON tab2.[manager id] = tab3.[manager id];
It seems that Access doesn't support SQL case statements, so my previous answer is incorrect. I'm leaving it there for anyone looking for the same problem with a SQL compliant database.
Apparently you can use a switch statement to achieve the same result; this example shows how a switch can be used. Hopefully that's more helpful.
Otherwise, if possible, switch to a real DB :)
Okay, I was slow off the mark with the fact that you can't use CASE, and Joe's use of Nz is probably your best bet, but there is another Access-specific alternative, presented here in case it fits your situation better:
select tab2.[employee name],
tab2.[employee id],
tab3.[chat info],
tab1.[manager id],
Iif(IsNull(tab3.[team name]), 'Unknown', tab3.[team name]) as [team name]
from tab2
left join tab1
on tab2.[employee id] = tab1.[employee id]
left join tab3
on tab2.[manager id] = tab3.[manager id]
In this situation, Iif( condition, trueAnswer, falseAnswer ) does the same thing as the Nz, but if your condition is something besides an IsNull it can be more flexible.
I'm not sure about Access, but in SQL normally you would left join your tables and you can use a CASE statement to add the conditional behaviour your looking for; access may not support this.
The example shown here is reasonably standard.
Wow, do access queries really look like that? Hmmm... Then perhaps something like this.
tab2.[employee name], tab2.[employee id], tab3.[chat info], tab1.[manager id], tab1.[manager id], case when tab3.[team name] is null then 'Unknown' else tab3.[team name] end as [team name]
where
tab2.[employee id] = tab1.[employee id] and tab2.[manager id] = tab3.[manager id];