After taking a look at some other posts, just saw/remembering that you can
use an alternate syntax for performing a Left Join on multiples fields that
is more palatable to the graphic designer; so instead of writing:
SELECT T1.CustNum, T1.Code, T1.Amt, T2.Code, T2.Amt, T3.Code, T3.Amt,
T4.Code, T4.Amt
FROM ((Table1 T1 Left JOIN Table1 AS T2 ON (T1.CustNum = T2.CustNum and
T2.OrderNo = 2)) Left Join Table1 as T3 ON (T1.CustNum = T3.CustNum and
T3.OrderNo = 3)) Left Join Table1 as T4 on (T1.CustNum = T4.CustNum and
T4.OrderNo = 4)
Where T1.OrderNo = 1
WITH OWNERACCESS OPTION;
you can write:
SELECT T1.CustNum, T1.Code, T1.Amt, T2.Code, T2.Amt, T3.Code, T3.Amt,
T4.Code, T4.Amt
FROM (([SELECT CustNum, Code, Amt FROM Table1 WHERE OrderNo=1]. AS T1 LEFT
JOIN [SELECT CustNum, Code, Amt FROM Table1 WHERE OrderNo=2]. AS T2 ON
T1.CustNum=T2.CustNum) LEFT JOIN [SELECT CustNum, Code, Amt FROM Table1
WHERE OrderNo=3]. AS T3 ON T1.CustNum=T3.CustNum) LEFT JOIN [SELECT CustNum,
Code, Amt FROM Table1 WHERE OrderNo=4]. AS T4 ON T1.CustNum=T4.CustNum
WITH OWNERACCESS OPTION;
However, on some occasions, particularly if I make some change to the
testing table Table1, Access has sometimes rewrote it under the wrong
following format:
SELECT T1.CustNum, T1.Code, T1.Amt, T2.Code, T2.Amt, T3.Code, T3.Amt,
T4.Code, T4.Amt
FROM (([SELECT CustNum, Code, Amt FROM Table1 WHERE OrderNo=1; ] AS T1 LEFT
JOIN [SELECT CustNum, Code, Amt FROM Table1 WHERE OrderNo=2; ] AS T2 ON
T1.CustNum=T2.CustNum) LEFT JOIN [SELECT CustNum, Code, Amt FROM Table1
WHERE OrderNo=3; ] AS T3 ON T1.CustNum=T3.CustNum) LEFT JOIN [SELECT
CustNum, Code, Amt FROM Table1 WHERE OrderNo=4; ] AS T4 ON
T1.CustNum=T4.CustNum
WITH OWNERACCESS OPTION;
but this form (the previous one, the one that is OK) seems to be a more
stable format than the form that I've used in my previous post.
With this form, by using the following subquery Query2b:
SELECT CustNum, Code, Amt, (Select Count(*) from Table2 as T2 where
T2.IdTable <= T1.IdTable and T2.CustNum = T1.CustNum) AS OrderNo
FROM Table2 AS T1
WITH OWNERACCESS OPTION;
it's possible to write the query that you need:
SELECT T1.CustNum, T1.Code, T1.Amt, T2.Code, T2.Amt, T3.Code, T3.Amt,
T4.Code, T4.Amt
FROM (([SELECT CustNum, Code, Amt FROM (Select * From Query2b WHERE
OrderNo=1) as Table1]. AS T1 LEFT JOIN [SELECT CustNum, Code, Amt FROM
(Select * From Query2b WHERE OrderNo=2) as Table1]. AS T2 ON T1.CustNum =
T2.CustNum) LEFT JOIN [SELECT CustNum, Code, Amt FROM (Select * From Query2b
WHERE OrderNo=3) as Table1]. AS T3 ON T1.CustNum = T3.CustNum) LEFT JOIN
[SELECT CustNum, Code, Amt FROM (Select * From Query2b WHERE OrderNo=4) as
Table1]. AS T4 ON T1.CustNum = T4.CustNum
WITH OWNERACCESS OPTION;
or, if you want to replace Query2b directly with its sql code:
SELECT T1.CustNum, T1.Code, T1.Amt, T2.Code, T2.Amt, T3.Code, T3.Amt,
T4.Code, T4.Amt
FROM (([SELECT CustNum, Code, Amt FROM (Select * From (SELECT CustNum, Code,
Amt, (Select Count(*) from Table2 as T2 where T2.IdTable <= T1.IdTable and
T2.CustNum = T1.CustNum) AS OrderNo
FROM Table2 AS T1) WHERE OrderNo=1) as Table1]. AS T1 LEFT JOIN [SELECT
CustNum, Code, Amt FROM (Select * From (SELECT CustNum, Code, Amt, (Select
Count(*) from Table2 as T2 where T2.IdTable <= T1.IdTable and T2.CustNum =
T1.CustNum) AS OrderNo
FROM Table2 AS T1) WHERE OrderNo=2) as Table1]. AS T2 ON T1.CustNum =
T2.CustNum) LEFT JOIN [SELECT CustNum, Code, Amt FROM (Select * From (SELECT
CustNum, Code, Amt, (Select Count(*) from Table2 as T2 where T2.IdTable <=
T1.IdTable and T2.CustNum = T1.CustNum) AS OrderNo
FROM Table2 AS T1) WHERE OrderNo=3) as Table1]. AS T3 ON T1.CustNum =
T3.CustNum) LEFT JOIN [SELECT CustNum, Code, Amt FROM (Select * From (SELECT
CustNum, Code, Amt, (Select Count(*) from Table2 as T2 where T2.IdTable <=
T1.IdTable and T2.CustNum = T1.CustNum) AS OrderNo
FROM Table2 AS T1) WHERE OrderNo=4) as Table1]. AS T4 ON T1.CustNum =
T4.CustNum
WITH OWNERACCESS OPTION;
and this is only with a maximum of four sales codes for each customer. In
your case, you can reach 15 sales codes; so obviously a much better solution
would be to use a temporary table to build your result by looping on each
column.
--
Sylvain Lafontaine, ing.
MVP - Technologies Virtual-PC
E-mail: sylvain aei ca (fill the blanks, no spam please)
Sylvain Lafontaine said:
This query is not easy because the same code doesn't repeat for each
CustNum in the same column. The most easy way would be to use a temporary
table to build your result. If you don't want to use a temporary table,
then you should add an order number and use it to build your result using
IIF() statements using a serie of Left Join:
CustNum.......Code.............Amt OrderNo
15893............A4..............15.10 1
15893............BK..............17.10 2
15893............Z4..............19.10 3
16893............TR..............12.10 1
16893............UK..............17.15 2
16893............WR.............22.50 3
16893............YT................5.53 4
SELECT T1.CustNum, T1.Code, T1.Amt, T2.Code, T2.Amt, T3.Code, T3.Amt,
T4.Code, T4.Amt
FROM ((Table1 T1 Left JOIN Table1 AS T2 ON (T1.CustNum = T2.CustNum and
T2.OrderNo = 2)) Left Join Table1 as T3 ON (T1.CustNum = T3.CustNum and
T3.OrderNo = 3)) Left Join Table1 as T4 on (T1.CustNum = T4.CustNum and
T4.OrderNo = 4)
Where T1.OrderNo = 1
WITH OWNERACCESS OPTION;
If IdTable is the primary key of the table, the following query will
automatically create the OrderNo field:
Select CustNum, Code, Amt, (Select Count(*) from Table1 as T2 where
T2.IdTable <= T1.IdTable and T2.CustNum = T1.CustNum) as OrderNo
From Table1 as T1
On SQL-Server, this work perfectly. However, on Access, this doesn't
work; as JET is known to bug when LEFT JOIN are too complex but if you use
a table with the column OrderNo already prepared, it works. Bad new is
that when created, you cannot open this query in the query designer any
more without Access rewriting incorrectly your query by removing the
parenthesis around « ON (T1.CustNum = T2.CustNum and T2.OrderNo = 2) » :
SELECT T1.CustNum, T1.Code, T1.Amt, T2.Code, T2.Amt, T3.Code, T3.Amt,
T4.Code, T4.Amt
FROM ((Table1 AS T1 LEFT JOIN Table1 AS T2 ON T1.CustNum = T2.CustNum and
T2.OrderNo = 2) LEFT JOIN Table1 AS T3 ON T1.CustNum = T3.CustNum and
T3.OrderNo = 3) LEFT JOIN Table1 AS T4 ON T1.CustNum = T4.CustNum and
T4.OrderNo = 4
WHERE T1.OrderNo = 1
WITH OWNERACCESS OPTION;
As you can see, Access is very crappy when it comes to complex expression
involving Left Join and/or Subqueries.
The best option for you would be to use a temporary table to build your
result.