Why is my LEFT JOIN an invalid operation (MS ACCESS 2003) - ms-access

I have a query which looks very much like this:
SELECT * FROM t1 LEFT JOIN t2 ON t1.aNumber = t2.aNumber;
When I try to run it, I get Invalid Operation. Both of the following queries run fine though:
SELECT * FROM t1;
SELECT * FROM t2;
So I'm guessing either the problem is really obvious or really complicated... How can I find the problem in this situation?
For completeness, here is the actual query (Query25) and all the other queries it refers to:
Query25
SELECT *
FROM [EXPORT PRICE AND Desc] LEFT JOIN Export_Union_active ON [EXPORT PRICE AND Desc].MaterialNumber = Export_Union_active.MaterialNumber;
EXPORT PRICE AND Desc
SELECT tblMMMaterials.MaterialNumber, tblMMMaterials.MaterialDescription AS name, Format(tblMMMaterials!SellingPrice,"Standard") AS SellingPrice, dbo_tblMMImages.Notes, tblMMMaterials.MFG, tblMMMaterials.Internet
FROM tblMMMaterials LEFT JOIN dbo_tblMMImages ON tblMMMaterials.MaterialID = dbo_tblMMImages.MaterialID
WHERE (((tblMMMaterials.Internet)=True));
Export_Union_active
select * from Export_Active UNION ALL select * from Export_Inactive;
Export_Active
SELECT tblMMMaterials.MaterialNumber, tblMMMaterials.Discontinued, 1 AS [check], tblMMMaterials.MFG
FROM tblMMMaterials
WHERE (((tblMMMaterials.Discontinued)=0) AND ((tblMMMaterials.MFG)="kheops"));
Export_Inactive
SELECT tblMMMaterials.MaterialNumber, tblMMMaterials.Discontinued, 0 AS [check], tblMMMaterials.MFG
FROM tblMMMaterials
WHERE (((tblMMMaterials.Discontinued)=1) AND ((tblMMMaterials.MFG)="kheops"));
And here are the tables refered to by all these queries (they are much bigger than this, but I trimmed out anything not used in any of the queries):
tblMMMaterials
MaterialID | Number | PK
MaterialNumber | Text
MaterialDescription | Text
SellingPrice | Currency
MFG | Text
Internet | Yes/No
Discontinued | Yes/No
tblMMImages
ImageID | AutoNumer | PK
MaterialID | Number
Notes | Memo

Related

MySQL first condition match priority

I have this data
+----+--------+---------------------------------+
| id | fromid | message |
+----+--------+---------------------------------+
| 1 | 1213 | this is just an example |
+----+--------+---------------------------------+
| 2 | 1992 | other random message |
+----+--------+---------------------------------+
| 3 | 1364 | example number three |
+----+--------+---------------------------------+
I need to search data where fromid='1992' or message LIKE '%example%'
if there is any result where fromid matches 1992 value, return this result, and ignore second condition
but if there is no result from first condition (fromid='1992'), return the result from second condition
can I do that on single query?
One way to do it is using a marker, and then limiting the results to the first row. An example using UNION:-
SELECT 1 AS match_type, my_table.*
from my_table
where fromid = 1992
UNION
SELECT 2 AS match_type, my_table.*
from my_table
WHERE message like '%example%'
ORDER BY match_type
LIMIT 1
Down side of this is that it still forces a relatively slow non indexed query using LIKE with a leading wildcard.
The following is an alternative. In most circumstance it would be pointless, but should the check on id be expected to bring back a record almost always, and the check on the LIKE just a very occasional condition (with only a single record ever returned) then it might be worthwhile as it would avoid having the do the slow LIKE condition searched unless necessary.
SELECT COALESCE(id, SELECT MAX(id) from my_table WHERE message like '%example%') AS id,
COALESCE(fromid, SELECT MAX(formed) from my_table WHERE message like '%example%') AS formed,
COALESCE(message, SELECT MAX(message) from my_table WHERE message like '%example%') AS message
FROM
(
SELECT id, fromid, message
FROM (SELECT 1 AS a_cnt) sub0
LEFT OUTER JOIN
(
SELECT id, fromid, message
from my_table
where fromid = 1992
) sub1
) sub2

Update table with data from multiple tables

I'm stuck on this one. I have three tables:
Table 1:
**ORDERS**
| ORDER_NO | PRODUCT_NO | CLIENT_NO | UNITS | ORDER_DATE |
Table 2:
**CLIENTS**
| CLIENT_NO | NAME | LOCATION | SELLER_NO | OWES | OVERPAID | CREDIT_LIMIT |
Table 3:
**PRODUCTS**
| PRODUCT_NO | DESCRIPTION | UNIT_PRICE | AVAILABLE_STOCK |
Now, what I have to do is to update column OWES in table CLIENTS so it contains total amount of money of all the orders they made.
This is as far as I got:
update CLIENTS set OWES = (select sum(o.UNITS) from ORDERS o where CLIENTS.CLIENT_NO = o.CLIENT_NO);
That seems to work just fine to get a total number of orders, but than I have to multiply it by the price of given item (whichever the order was for) and I get myself confused.
I tried for example:
update CLIENTS set OWES = ( select sum(o.UNITS) from ORDERS o where CLIENTS.CLIENT_NO = o.CLIENT_NO)*(select UNIT_PRICE from PRODUCTS where PRODUCT_NO= any(select PRODUCT_NO from ORDERS));
But that returns ERROR 1242 (21000): Subquery returns more than 1 row
What am I doing wrong? Would it be better to use update CLIENTS as ( some complicated sub query goes here) ?
Can anyone help me out and be so kind to throw in some explanation why such solution and not some other? It just seem like I didn't get something on more basic level and now I'm struggling.
Thanks in advance.
I think you can just do a join in the subquery and do the appropriate aggregation:
update CLIENTS
set OWES = (select sum(o.UNITS * p.unit_price)
from ORDERS o join
products p
on o.product_no = p.product_no
where CLIENTS.CLIENT_NO = o.CLIENT_NO
);
Your syntax is a little off. The general syntax for updating from other tables is:
UPDATE table1
JOIN table2 ON table2.mycolumn = table1.mycolumn
JOIN (
SELECT foo, SUM(bar) as sumbar FROM table3) table3sum ON table3sum.foo = table1.foo
SET
table1.foo = table2.bar,
table1.baz = table3sum.sumbar

sql join data from two tables

I wonder if someone help me to join data from two tables...spending all the day didn't manage...
Code 1 selects:
Year | Turnover1 | Quantity1 | EurPerOrder1
SELECT Year(table1.ContractDate) AS Year,
Sum(table1.TPrice) AS Turnover1,
Count(table1.id) AS Quantity1,
ROUND(Sum(table1.TPrice) / Count(table1.id), 0) AS EurPerOrder1
FROM table1
GROUP BY Year(table1.ContractDate) * 100
ORDER BY table1.ContractDate DESC
Code2 selects:
Year | Turnover2 | Quantiry2 | EurPerOrder2
SELECT Year(table2.date) AS Year,
Sum(table2.price) AS Turnover2,
Count(table2.rid) AS Quantiry2,
ROUND(Sum(table2.price) / Count(table2.rid), 0) AS EurPerOrder2
FROM table2
GROUP BY Year(table2.date) * 100
ORDER BY table2.date DESC
And I need to join data like:
Year | Turnover1 | Quantity1 | EurPerOrder1 | Turnover2 | Quantiry2 | EurPerOrder2
I need to have all data from both tables grouped by years. Even table2 doesnt have year 2013 anyway I would like it showed 0 or empty...
I have tried different ways using examples but nothing worked so I think the problem can occur because second table doesn't have all the years which are on table1...
First: you can read pretty good explanation about the JOINS here
Ok, according the question you need LEFT JOIN. This means all data from table1 and only matching data from table2.
The SELECT must look like:
SELECT Year(table1.ContractDate) AS Year,
Sum(table1.TPrice) AS Turnover1,
Count(table1.id) AS Quantiry1,
ROUND(Sum(table1.TPrice) / Count(table1.id), 0) AS EurPerOrder1,
Sum(table2.price) AS Turnover2,
Count(table2.rid) AS Quantiry2,
ROUND(Sum(table2.price) / Count(table2.rid), 0) AS EurPerOrder2
FROM
table1 t1
LEFT JOIN table2 t2 ON Year(table1.ContractDate) = Year(table2.date)
GROUP BY
Year(table1.ContractDate) * 100, Year(table2.date) * 100
ORDER BY
table1.ContractDate DESC, table2.date DESC
Of course you need to process NULL values. See link
Please check SQL and correct it if there are erreors. I don't have live data to check (by running it).

Query1 Join with Query2 but Query2 use the result of Query1, How to do that with just 1 query?

Ok, I have a complicated query to get all article details, each article has many versions. I have a need to get details of article with latest version only (ie take the max version). Here is the table:
+------------+-----------+----------+
| ArticleID | Detail | Version |
+------------+-----------+----------+
| 1 | detail1 | 1 |
| 1 | detail2 | 1 |
| 1 | detail3 | 2 |
| 1 | detail4 | 2 |
| 3 | detail3 | 2 |
| 3 | detail6 | 2 |
| 3 | detail4 | 3 |
+------------+-----------+----------+
Now user just provides a detail & the query will take all details of all articles with version=max(version)
Suppose that if we don't care about max version, then a simple query could be
Select * from articleTb where Detail like '%3'
It will print out:
+------------+-----------+----------+
| ArticleID | Detail | Version |
+------------+-----------+----------+
| 1 | detail3 | 2 |
| 3 | detail3 | 2 |
+------------+-----------+----------+
But this doesn't meet the requirement cos the result should not have this record 3 - detail3 - 2 cos it doesn't contain the max version of articleID=3.
Let say user search for Detail like '%4', then a correct query should be:
ArticleID - Detail - Version
+----+-----------+----+
| 1 | detail4 | 2 |
+----+-----------+----+
| 3 | detail4 | 3 |
+----+-----------+----+
The 2 records appear cos they belongs to the article with max version. Explain, 2 is the maxversion of articleID=1 so it matches the condition, & 3 is the max version of articleID=3 so it also matches the condition.
So here is what i did,
select * from (Select * from articleTb where Detail like '%3') tb1
Join (select articleID, max(version) maxversion from articleTb where
Detail like '%3' group by articleID) tb2
on tb1.articleID=tb2.articleID and tb1.version=tb2.maxversion
However, for the above query the system have to duplicate the task where Detail like '%3' which is not good. Besides, my real world query1 is much more complicated than where Detail like '%3', then if i do like the above then the query will implement the same job TWICE? & that is very inefficient.
So how to deal this problem?
To improve performance, remove the unnecessary inline view, e.g.
SELECT tb1.*
FROM articleTb tb1
JOIN ( SELECT b.articleID
, MAX(b.version) AS maxversion
FROM articleTb b
WHERE b.Detail LIKE '%3'
GROUP BY b.articleID
) tb2
ON tb1.articleID = tb2.articleID
AND tb1.version = tb2.maxversion
WHERE tb1.Detail LIKE '%3'
and...
make sure you have appropriate indexes. A covering index with a leading column of article may enable MySQL to use the index to optimize the GROUP BY (avoiding a "Using filesort" operation.)
... ON articleTb (articleID, version, detail)
MySQL may also be able to use that index for the join to tb1; the derived table (inline view) won't have an index.
You can confirm the execution plan with an EXPLAIN.
I would use a CTE to create a table that contains the article id and the version id, then use that in my main query to filter down to the most recent version.
with latest as
(
select articleId, max(version) as version from articleTb
)
select ....
from articleTb a
inner join latestl on a.articleid = l.articleid and l.version = a.version
Use of aggregate table will helpful.
Let me describe a scenario first. Day 1, you get a flat file first time ever.
1. Load that in a staging table.
2. Find ArticleID, MAx (Version) for each Article ID, and store in the aggregate table.
3. Left outer join the stage table with the aggregate table joining on article ID. Pick the higher version. This will lead to your result.
4. Truncate the staging table.
Next day when a new feed arrives, the file will again be loaded into the truncated table, and left joined.
You can add a few audit fields in aggregate table such as date when that file arrived, maybe file name too. I had used this method in one of the projects in a insurance companies that resulted into several fold performance gain.
This is your query:
select *
from (Select * from articleTb where Detail like '%3'
) tb1 Join
(select articleID, max(version) maxversion
from articleTb
where Detail like '%3'
group by articleID
) tb2
on tb1.articleID=tb2.articleID and tb1.version=tb2.maxversion;
You are trying to get the last version of a particular type of article. Another approach is to use not exists:
select *
from articleTb t
where Detail like '%3' and
not exists (select 1
from articleTb t2
where t2.articleID = t1.articleID and
t2.Detail like '%3'
t2.version > t.version
);
This is saying: "Get me all the rows from articleTb where Detail ends in 3 and there isn't another version that is higher".
To improve performance, create an index on: articleTb(articleID, Detail, version). The one question is whether t2.Detail like '%3' is needed for the subquery -- does that condition filter articles or versions within an article? If it is not needed, then remove the index and change the condition to articleTb(articleID, version).

mysql small count issue on same table

Please find db structure as following...
| id | account_number | referred_by |
+----+-----------------+--------------+
| 1 | ac203003 | ac203005 |
+----+-----------------+--------------+
| 2 | ac203004 | ac203005 |
+----+-----------------+--------------+
| 3 | ac203005 | ac203004 |
+----+-----------------+--------------+
I want to achieve following results...
id, account_number, total_referred
1, ac203005, 2
2, ac203003m 0
3, ac203004, 1
And i am using following query...
SELECT id, account_number,
(SELECT count(*) FROM `member_tbl` WHERE referred_by = account_number) AS total_referred
FROM `member_tbl`
GROUP BY id, account_number
but its not giving expected results, please help. thanks.
You need to use table aliases to do this correctly:
SELECT id, account_number,
(SELECT count(*)
FROM `member_tbl` t2
WHERE t2.referred_by = t1.account_number
) AS total_referred
FROM `member_tbl` t1;
Your original query had referred_by = account_number. Without aliases, these would come from the same row -- and the value would be 0.
Also, I removed the outer group by. It doesn't seem necessary, unless you want to remove duplicates.
One idea is to join the table on itself. This way you can avoid the subquery. There might be performance gains with this approach.
select b.id, b.account_number, count(a.referred_by)
from member_tbl a inner join member_tbl b
on a.referred_by=b.account_number
group by (a.referred_by);
SQL fiddle: http://sqlfiddle.com/#!2/b1393/2
Another test, with more data: http://sqlfiddle.com/#!2/8d216/1
select t1.account_number, count(t2.referred_by)
from (select account_number from member_tbl) t1
left join member_tbl t2 on
t1.account_number = t2.referred_by
group by t1.account_number;
Fiddle for your data
Fiddle with more data