SQL with 3 criteria using Access - ms-access

Morning All
I am using Access 2010 and currently have the below SQL which works fine:
Code:
DELETE DISTINCTROW tbl_added.*
FROM tbl_added INNER JOIN tbl_removed ON (tbl_added.SPECIAL_NEED_TYPE = tbl_removed.SPECIAL_NEED_TYPE) AND (tbl_added.NUM_CUST = tbl_removed.NUM_CUST);
I am trying to add another criteria but getting an error:
Code:
DELETE DISTINCTROW tbl_added.*
FROM tbl_added INNER JOIN tbl_removed ON (tbl_added.SPECIAL_NEED_TYPE = tbl_removed.SPECIAL_NEED_TYPE) AND (tbl_added.NUM_CUST = tbl_removed.NUM_CUST) AND (tbl_added.ADDED_REMOVAL_DT < tbl_removed.ADDED_REMOVAL_DT) ;
Error Received:
Could not delete from specified tables
The last criteria I have added is a date

When joining on any operator that is not =, your recordset becomes non-updateable. That means that you can't edit or delete.
You could move all comparisons to the WHERE clause, and use a CROSS JOIN instead, like this:
DELETE DISTINCTROW tbl_added.*
FROM tbl_added, tbl_removed
WHERE (tbl_added.SPECIAL_NEED_TYPE = tbl_removed.SPECIAL_NEED_TYPE) AND (tbl_added.NUM_CUST = tbl_removed.NUM_CUST) AND (tbl_added.ADDED_REMOVAL_DT < tbl_removed.ADDED_REMOVAL_DT) ;
However, that's still not updateable, since a CROSS JOIN is not updateable.
The solution is to keep all = comparisons in the INNER JOIN, and move all other comparisons to the WHERE clause:
DELETE DISTINCTROW tbl_added.*
FROM tbl_added INNER JOIN tbl_removed ON (tbl_added.SPECIAL_NEED_TYPE = tbl_removed.SPECIAL_NEED_TYPE) AND (tbl_added.NUM_CUST = tbl_removed.NUM_CUST)
WHERE (tbl_added.ADDED_REMOVAL_DT < tbl_removed.ADDED_REMOVAL_DT) ;
This keeps the recordset updateable, and still allows you to use a < operator.

In Access SQL you can't join on "<".
You'll have to use a subquery of some kind or create a temp table with those IDs to delete, then join to this.
Edit:
Well, you "can" but not in the GUI designer (see comment from Erik).
So, add the join in the GUI designer the usual way. That will create a join using "=". Then switch to SQL view and change "=" to "<".
It should now run without an error, but you will not be able to switch back to the GUI designer.

Related

join results into new table?

I can successfully join two tables, but i'm trying to output the results of the join into a new table.
The following throws a syntax error, but works if the "into" line is omitted.
To be clear - not having problems w/ the join, but the "into" statement.
SELECT evictions.uniqueid_neighborhoods.id, evictions.uniqueid_neighborhoods.neighbor_1,
evictions.sanfrancisco_evictions_backup2.Breach,
evictions.sanfrancisco_evictions_backup2.NonPayment,
evictions.sanfrancisco_evictions_backup2.Nuisance,
evictions.sanfrancisco_evictions_backup2.IllegalUse
** This causes code to fail
into evictions_by_commArea
from evictions.uniqueid_neighborhoods
inner join evictions.sanfrancisco_evictions_backup2 on evictions.uniqueid_neighborhoods.id = evictions.sanfrancisco_evictions_backup2.id
MySQL uses CREATE TABLE AS:
CREATE TABLE evictions_by_commArea as
SELECT un.id, un.neighbor_1,
sfe.Breach,
sfe.NonPayment,
sfe.Nuisance,
sfe.IllegalUse
from evictions.uniqueid_neighborhoods un join
evictions.sanfrancisco_evictions_backup2 sfe
on un.id = sfe.id;
I also introduced able aliases so the query is easier to write and to read.

MAX(Date) is giving empty result

I have a table with exchange rate like below
And I am using the maxofdate to pick all these values based on currency code. But the query is giving blank.
Select USDAMOUNT * dbo.EXCHANGERATEAMT
from dbo.Amount_monthly
Left Join dbo.EXCHANGERATE on dbo.Amount_monthly.Currencycode=dbo.EXCHANGERATE.fromcurrencycode
WHERE ValidToDateTime = (Select MAX(ValidToDateTime) from dbo.EXCHANGERATE)
AND dbo.EXCHANGERATE.EXCHANGERATETYPECODE = 'DAY'
Using this statement
CONVERT(DATE,ValidToDateTime) = CONVERT(DATE,GETDATE()-1)
instead of subquery is giving me expected result.
Can someone correct this.
thanks in advance.
If I understand correctly, you need two things. First, the condition for the max() needs to match the condition in the outer query. Second, if you really want a left join, then conditions on the second table need to go in the on clause.
The resulting query looks like:
Select . . .
from dbo.Amount_monthly am Left Join
dbo.EXCHANGERATE er
on am.Currencycode = er.fromcurrencycode and
er.ValidToDateTime = (Select max(er2.ValidToDateTime)
from dbo.EXCHANGERATE er2
where er2.EXCHANGERATETYPECODE = 'DAY'
) and
er.EXCHANGERATETYPECODE = 'DAY';
I would write this using window functions, but that is a separate issue.
Try removing WHERE clause for ValidToDateTime and include it in the JOIN as AND condition
SELECT USDAMOUNT * dbo.EXCHANGERATEAMT
FROM dbo.Amount_monthly
LEFT JOIN dbo.EXCHANGERATE
ON dbo.Amount_monthly.Currencycode = dbo.EXCHANGERATE.fromcurrencycode
AND ValidToDateTime = (SELECT MAX(ValidToDateTime) --remove WHERE clause
FROM dbo.EXCHANGERATE)
AND dbo.EXCHANGERATE.EXCHANGERATETYPECODE = 'DAY';
I cleaned up your query a bit: as the other folks mentioned you needed to close the parentheses around the MAX(Date) sub-query, and if you reference a LEFT JOINed table in the WHERE clause, it behaves like an INNER JOIN, so I changed to in INNER. You also had "dbo" sprinkled in as a field prefix, but that (the namespace) only prefixes a database, not a field. I added the IS NOT NULL check just to avoid SQL giving the "null values were eliminated" SQL warning. I used the aliases "am" for the first table and "er" for the 2nd, which makes it more readable:
SELECT am.USDAMOUNT * er.EXCHANGERATEAMT
FROM dbo.Amount_monthly am
JOIN dbo.EXCHANGERATE er
ON am.Currencycode = er.fromcurrencycode
WHERE er.ValidToDateTime = (SELECT MAX(ValidToDateTime) FROM dbo.EXCHANGERATE WHERE ValidToDateTime IS NOT NULL)
AND er.EXCHANGERATETYPECODE = 'DAY'
If you're paranoid like I am, you might also want to make sure the exchange rate is not zero to avoid a divide-by-zero error.

Running an UPDATE query within MySQL (with relationships)

Some of you will have seen me trying to learn how to run UPDATE queries on MySQL (for those of you who helped out - THANK YOU). However, whilst progress has certainly been made, I am still struggling to simply update one column with data from another - and can't get it to work.
If I run the following SELECT query, I see several thousand records that match
SELECT
`agr_addressbook`.`gtxr2_product_family` AS `gtxr2_product_family`,
`gtxuk_r2_machine`.`product_family` AS `product_family`
FROM (((`agr_addressbook`
JOIN `agr_addressbook_extra` ON ((`agr_addressbook`.`contact_id` = `agr_addressbook_extra`.`contact_id`)))
JOIN `gtxuk_machine` ON ((`agr_addressbook_extra`.`contact_value` = `gtxuk_machine`.`machine_id`)))
JOIN `gtxuk_r2_machine` ON ((CONVERT(`gtxuk_machine`.`machine_desc` USING utf8) = `gtxuk_r2_machine`.`machine_desc`)))
WHERE (`agr_addressbook_extra`.`contact_name` = 'mac_type')
However, when I run the following update query - it doesn't update a single value - meaning that I have messed up somewhere:
UPDATE agr_addressbook ea
JOIN agr_addressbook_extra eae ON eae.contact_id = ea.contact_id
JOIN gtxuk_machine hm ON hm.machine_id = eae.contact_value
JOIN gtxuk_r2_machine hrm ON hrm.machine_desc = CONVERT(hm.machine_desc USING utf8)
SET ea.gtxr2_product_family = hrm.product_family
WHERE eae.contact_name = 'mac_type'
Can anyone see where I'm going wrong?
Thank you (yet again).
This (or something very similar) might work:
UPDATE agr_addressbook ea
SET ea.gtxr2_product_family = (
SELECT hrm.product_family FROM agr_addressbook_extra eae
JOIN gtxuk_machine hm ON hm.machine_id = eae.contact_value
JOIN gtxuk_r2_machine hrm ON hrm.machine_desc = CONVERT(hm.machine_desc USING utf8)
WHERE eae.contact_name = 'mac_type' AND eae.contact_id = ea.contact_id)
Your problem may have to do with the way that UPDATE parameters work. Think about how you are passing a JOINed table as the table to perform changes to.

Microsoft Access Update Statement with Inner Joins and Subqueries

I am having a tough time figuring out how to do this update query. Basically I need to update a table named tblOpenJobs. It needs to be updated with the dbo_WorkOrders table with the Max Install date. But there is not direct relationship between those two tables you need to have the dbo_premise table between. Here is my query, what am I doing wrong?
UPDATE tblOpenJobs
INNER JOIN (dbo_Premise INNER JOIN dbo_WorkOrders w (WHERE w.InstallDate IN
(SELECT MAX(InstallDate) FROM dbo_WorkOrders WHERE dbo_WorkOrders.PremiseKey = w.PremiseKey))
ON (dbo_Premise.PremiseKey = w.PremiseKey)
ON tblOpenJobs.ServiceOrderNum = dbo_Premise.AccountNumber
SET tblOpenJobs.InstallerID = w.InstallerID,
tblOpenJobs.InstallDate= w.InstallDate,
tblOpenJobs.New_Serial_num= w.NewSerial,
tblOpenJobs.Old_Reading= w.OldRead;
I checked this in Access 2007 query window:
Your query seems neither Transact-SQL, neither Access, as the two have different syntax.
In Access, table aliasing must use the keyword AS, while Transact-SQL does not require:
UPDATE ((tblOpenJobs
INNER JOIN dbo_Premise
ON tblOpenJobs.ServiceOrderNum = dbo_Premise.AccountNumber)
INNER JOIN dbo_WorkOrders AS w
ON dbo_Premise.PremiseKey = w.PremiseKey)
SET tblOpenJobs.InstallerID = w.InstallerID,
tblOpenJobs.InstallDate = w.InstallDate,
tblOpenJobs.New_Serial_num = w.NewSerial,
tblOpenJobs.Old_Reading = w.OldRead
WHERE (w.InstallDate IN
(SELECT MAX(InstallDate)
FROM dbo_WorkOrders
WHERE dbo_WorkOrders.PremiseKey = w.PremiseKey))
This is correct in syntax, but I'm not sure it can update your data, as multi-table linked update is not easy in Access.

MYSQL get other table data in a join

I am currently running this SQL
SELECT jm_recipe.name, jm_recipe.slug
FROM jm_recipe
LEFT JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
WHERE jm_category_recipe.category_id = $cat"
This returns the desired results except that I also need to return the name of the category that the recipe I am looking for is in, to do this I tried to add the field in to my SELECT statement and also add the table into the FROM clause,
SELECT jm_recipe.name, jm_recipe.slug, jm_category_name
FROM jm_recipe, jm_category
LEFT JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
WHERE jm_category_recipe.category_id = $cat"
However this just returns no results, what am i doing wrong?
You need to join both tables:
SELECT jm_recipe.name, jm_recipe.slug, jm.category_name
FROM jm_recipe
INNER JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
INNER JOIN jm_category ON jm_recipe.recipe_id = jm_category.recipe_id
WHERE jm_category_recipe.category_id = $cat
I've changed the joins to inner joins as well. You might want to make them both LEFT joins if you have NULLs and want them in the result.
Also, you're vulnerable to SQL Injection by simply copying over $cat.
Here's some PHP specific info for you (I'm assuming you're using PHP.)