ACCESS SQL query: adding a new field? - sql

I would like to add a field to a existing query that doesn't get affected from 'Where function'
For example,
This is the original code....
SELECT SHELL_Payables.PoolNum,
A.[Code], B.[Program] AS Program, A.PayableAmt, C.ReceivableAmt INTO [New Data]
FROM A INNER JOIN B ON A.ID=B.ID
INNER JOIN C ON A.Num=B.Num
WHERE (((A.AccountingPeriod)<=[AccountingYearMonth]));
I would like to add A.PayableAmt again but this time where clause (accountingperiod <= accountingyearMonth) should not be applied to this field...
Any ideas? It would be much appreciated.

To use union and select into, you would need to write your query something like this:
SELECT *
INTO [New Data]
FROM (
SELECT PoolNum
,A.[Code]
,B.[Program] AS Program
,A.PayableAmt
,C.ReceivableAmt
FROM A
INNER JOIN B ON A.ID = B.ID
INNER JOIN C ON A.Num = B.Num
WHERE A.AccountingPeriod <= AccountingYearMonth
UNION
SELECT PoolNum
,A.[Code]
,B.[Program] AS Program
,A.PayableAmt
,C.ReceivableAmt
FROM A
INNER JOIN B ON A.ID = B.ID
INNER JOIN C ON A.Num = B.Num
)
UPDATE
If you want to add another PayableAmt column to the same row, maybe you can join back to the table A something like this:
SELECT t.PoolNum
,a.[Code]
,a.[Program] AS Program
,t.PayableAmt
,a.PayableAmt AS NewPayableAmt
,C.ReceivableAmt
INTO [New Data]
FROM A
LEFT JOIN
(
SELECT
PoolNum
,A.[Code]
,B.[Program] AS Program
,A.PayableAmt
,C.ReceivableAmt
FROM A
INNER JOIN B ON A.ID = B.ID
INNER JOIN C ON A.Num = B.Num
WHERE A.AccountingPeriod <= AccountingYearMonth
) t
ON t.Code = A.Code --assuming this is unique
INNER JOIN B ON A.ID = B.ID
INNER JOIN C ON A.Num = B.Num

Related

Is it possible to do a nested left join within another left join?

So I want to do something like this:
SELECT ACC_NO
FROM
TABLENAME A
LEFT JOIN
(
TABLENAME B
LEFT JOIN TABLENAME C
ON B.FIELDNAME = C.FIELDNAME
) D
ON A.FIELDNAME = D.FIELDNAME
How would I achieve this?
Yes it is possible, Try like below
SELECT A.ACC_NO,A.FIELDNAME
FROM
TABLENAME A
LEFT JOIN
(
select B.* from TABLENAME B
LEFT JOIN TABLENAME C
ON B.FIELDNAME = C.FIELDNAME
) D
ON A.FIELDNAME = D.FIELDNAME
Yes, you can:
SELECT ACC_NO
FROM TABLENAME A LEFT JOIN
(TABLENAME B LEFT JOIN
TABLENAME C
ON B.FIELDNAME = C.FIELDNAME
) -- No alias is necessary
ON A.FIELDNAME = B.FIELDNAME;
However, this is unnecessary and verbose. Instead:
SELECT ACC_NO
FROM TABLENAME A LEFT JOIN
TABLENAME B
A.FIELDNAME = B.FIELDNAME LEFT JOIN
TABLENAME C
ON B.FIELDNAME = C.FIELDNAME;
I assume your query is actually more complex. This version is presumably equivalent to:
SELECT A.ACC_NO
FROM TABLENAME A
Unless you are interested in actually seeing duplicates that might be generated by the JOINs.

SQL summations with multiple outer joins

I have tables a, b, c, and d whereby:
There are 0 or more b rows for each a row
There are 0 or more c rows for each a row
There are 0 or more d rows for each a row
If I try a query like the following:
SELECT a.id, SUM(b.debit), SUM(c.credit), SUM(d.other)
FROM a
LEFT JOIN b on a.id = b.a_id
LEFT JOIN c on a.id = c.a_id
LEFT JOIN d on a.id = d.a_id
GROUP BY a.id
I notice that I have created a cartesian product and therefore my sums are incorrect (much too large).
I see that there are other SO questions and answers, however I'm still not grasping how I can accomplish what I want to do in a single query. Is it possible in SQL to write a query which aggregates all of the following data:
SELECT a.id, SUM(b.debit)
FROM a
LEFT JOIN b on a.id = b.a_id
GROUP BY a.id
SELECT a.id, SUM(c.credit)
FROM a
LEFT JOIN c on a.id = c.a_id
GROUP BY a.id
SELECT a.id, SUM(d.other)
FROM a
LEFT JOIN d on a.id = d.a_id
GROUP BY a.id
in a single query?
Your analysis is correct. Unrelated JOIN create cartesian products.
You have to do the sums separately and then do a final addition. This is doable in one query and you have several options for that:
Sub-requests in your SELECT: SELECT a.id, (SELECT SUM(b.debit) FROM b WHERE b.a_id = a.id) + ...
CROSS APPLY with a similar query as the first bullet then SELECT a.id, b_sum + c_sum + d_sum
UNION ALL as you suggested with an outer SUM and GROUP BY on top of that.
LEFT JOIN to similar subqueries as above.
And probably more... The performance of the various solutions might be slightly different depending on how many rows in A you want to select.
SELECT a.ID, debit, credit, other
FROM a
LEFT JOIN (SELECT a_id, SUM(b.debit) as debit
FROM b
GROUP BY a_id) b ON a.ID = b.a_id
LEFT JOIN (SELECT a_id, SUM(b.credit) as credit
FROM c
GROUP BY a_id) c ON a.ID = c.a_id
LEFT JOIN (SELECT a_id, SUM(b.other) as other
FROM d
GROUP BY a_id) d ON a.ID = d.a_id
Can also be done with correlated subqueries:
SELECT a.id
, (SELECT SUM(debit) FROM b WHERE a.id = b.a_id)
, (SELECT SUM(credit) FROM c WHERE a.id = c.a_id)
, (SELECT SUM(other) FROM d WHERE a.id = d.a_id)
FROM a

Syntax for multiple joins in sql

Working on Oracle: I am attempting to do an inner self join, with a where clause, then take that result and do a left outer join on it:
(select * from table1 A
inner join
select * from table1 B
on A.id = B.id
where
A.id is not null and B.id is not null) C
left outer join
select * from table2 D
on C.id = D.id
Somehow I am syntactically challenged and can't make this work. Can't seem to find the right syntax anywhere.
Just the put the where clause at the end. The database will get it right:
select *
from table1 A
inner join table1 B on A.id = B.id
left join table2 D on D.id = A.id
where A.id is not null
In this case, we can take advantage of the logical transitive property for your id column joins and where clause.
Your second join needs to be joined to a query add a select * from at the beginning
select * from (select * from table1 A
inner join
select * from table1 B
on A.id = B.id
where
A.id is not null and B.id is not null) C
left outer join
select * from table2 D
on C.id = D.id

Joining many tables together using key from first table for all joins?

I would like to do something like this but can't get it to work:
SELECT A.*,B.*,C.* FROM tableA A LEFT JOIN
B ON A.ID = B.ID
C ON A.ID = C.ID
I.e. I need to use a field from the first table for all joins as tableB and tableC don't
has any fields to link them together.
Can this be done?
you missed a join !
SELECT A.*,B.*,C.* FROM tableA A
LEFT JOIN
B ON A.ID = B.ID
left join
C ON A.ID = C.ID
Try this one -
SELECT *
FROM dbo.tableA A
LEFT JOIN dbo.B ON A.ID = B.ID
LEFT JOIN dbo.C ON A.ID = C.ID

how to eliminate duplicate results from joined sql statement

i have four tables which are related like this:
TABLE A: 1 to many with TABLE B
TABLE B: 1 to many with TABLE C
TABLE D: many to 1 with TABLE B
I would like to create a result set which contains no duplicates.
SELECT A.f1
A.f2
B.f1
C.f1
D.f1
from A LEFT JOIN (B INNER JOIN D on D.fk_b = B.id) on A.id = B.fk_a
LEFT JOIN C on C.fk_b = B.id
Some but not all records are duplicated. Only the records from TABLE D which have the same FK to TABLE B.
If there are 2 the same D.fk_B fields then i would like to select only the first one. My INNER JOIN would become something like:
B INNER JOIN TOP 1 D on.....
But that's not possible?
Thank you!
Assuming that the structure in question is near the one shown bellow,
The following SELECT statement will show you just the primary keys, briefly giving an idea about what data is being returned.
SELECT
A.id AS `A_id`,
B.id AS `B_id`,
COALESCE(C.id, 0) AS `C_id`,
COALESCE(
(SELECT D.id FROM D WHERE D.fk_b = B.id LIMIT 1), 0
) AS `D_id`
FROM B
INNER JOIN A ON (B.fk_a = A.id)
LEFT JOIN C ON (B.id = C.fk_b);
Now the select you've asked for:
SELECT
A.f1 AS `A_f1`,
A.f2 AS `A_f2`,
B.f1 AS `B_f1`,
COALESCE(C.f1, '-') AS `C_f1`,
COALESCE(
(SELECT D.f1 FROM D WHERE D.fk_b = B.id LIMIT 1), '-'
) AS `D_f1`
FROM B
INNER JOIN A ON (B.fk_a = A.id)
LEFT JOIN C ON (B.id = C.fk_b);
Code above was tested and worked fine on MySQL 5.6
It appears that you have cartesian join.
You could try just putting DISTINCT infront of you column definition or you could so subqueries to link the tables together.
Try
SELECT DISTINCT A.f1
A.f2
B.f1
C.f1
D.f1
from A LEFT JOIN (B INNER JOIN D on D.fk_b = B.id) on A.id = B.fk_a
LEFT JOIN C on C.fk_b = B.id
You can do this:
B INNER JOIN TOP 1 D on.....
Like this
B INNER JOIN (SELECT TOP 1 fields from table) D ON ...
Try this:
SELECT DISTINCT A.f1
A.f2
B.f1
C.f1
D.f1
from A
LEFT JOIN (B INNER JOIN (SELECT DISTINCT fk_b FROM D) D on D.fk_b = B.id)
on A.id = B.fk_a
LEFT JOIN C on C.fk_b = B.id