Access SQL Subquery in From - sql

I'm learning Access and SQL, but I have a problem using subqueries in the from clause I can't seem to figure out.
Select *
From (LongSubQuery) as a, (LongSubQuery) as b, (LongSubQuery) as c
Where a.field=b.field=c.field;
This works perfectly as long as each of the statements A, B, and C in the from clause returns a record. If the where clause in any of the three statements prevents the return of a record, then none of the statements will return a result. I've tried various NZ and is not null statements with no luck. I'm suspicious it is actually caused by the last line of code making the fields equivalent. Is there any way around this?

First of all, when you do something like select * from A, B, C (where A, B, C are data sets), you are returning the cartesian product of A, B, C; in other words, you will have #(A)*#(B)*#(C) rows (where #(A) is the number of rows in set A). So, of course, if one of the sets is empty, the whole set is empty.
Possible solution: Use unilateral joins:
select *
from
(select ...) as a
left join (select ...) as b on a.aField = b.aField ...
left join (select ...) as c on b.aField = c.aFiedl ...
left join returns all the rows on the left side of the relation and all the matching rows of the right side of the relation if it is fulfilled, and null values if it is not fulfilled.
Be careful when you make the relations. Be sure you use the fields you need. Notice that in this case you can define the condition you are using in the where clause directly in the join construction.

Related

Oracle: Use only few tables in WHERE clause but mentioned more tables in 'FROM' in a jon SQL

What will happen in an Oracle SQL join if I don't use all the tables in the WHERE clause that were mentioned in the FROM clause?
Example:
SELECT A.*
FROM A, B, C, D
WHERE A.col1 = B.col1;
Here I didn't use the C and D tables in the WHERE clause, even though I mentioned them in FROM. Is this OK? Are there any adverse performance issues?
It is poor practice to use that syntax at all. The FROM A,B,C,D syntax has been obsolete since 1992... more than 30 YEARS now. There's no excuse anymore. Instead, every join should always use the JOIN keyword, and specify any join conditions in the ON clause. The better way to write the query looks like this:
SELECT A.*
FROM A
INNER JOIN B ON A.col1 = B.col1
CROSS JOIN C
CROSS JOIN D;
Now we can also see what happens in the question. The query will still run if you fail to specify any conditions for certain tables, but it has the effect of using a CROSS JOIN: the results will include every possible combination of rows from every included relation (where the "A,B" part counts as one relation). If each of the three parts of those joins (A&B, C, D) have just 100 rows, the result set will have 1,000,000 rows (100 * 100 * 100). This is rarely going to give the results you expect or intend, and it's especially suspect when the SELECT clause isn't looking at any of the fields from the uncorrelated tables.
Any table lacking join definition will result in a Cartesian product - every row in the intermediate rowset before the join will match every row in the target table. So if you have 10,000 rows and it joins without any join predicate to a table of 10,000 rows, you will get 100,000,000 rows as a result. There are only a few rare circumstances where this is what you want. At very large volumes it can cause havoc for the database, and DBAs are likely to lock your account.
If you don't want to use a table, exclude it entirely from your SQL. If you can't for reason due to some constraint we don't know about, then include the proper join predicates to every table in your WHERE clause and simply don't list any of their columns in your SELECT clause. If there's a cost to the join and you don't need anything from it and again for some very strange reason can't leave the table out completely from your SQL (this does occasionally happen in reusable code), then you can disable the joins by making the predicates always false. Remember to use outer joins if you do this.
Native Oracle method:
WITH data AS (SELECT ROWNUM col FROM dual CONNECT BY LEVEL < 10) -- test data
SELECT A.*
FROM data a,
data b,
data c,
data d
WHERE a.col = b.col
AND DECODE('Y','Y',NULL,a.col) = c.col(+)
AND DECODE('Y','Y',NULL,a.col) = d.col(+)
ANSI style:
WITH data AS (SELECT ROWNUM col FROM dual CONNECT BY LEVEL < 10)
SELECT A.*
FROM data a
INNER JOIN data b ON a.col = b.col
LEFT OUTER JOIN data c ON DECODE('Y','Y',NULL,a.col) = b.col
LEFT OUTER JOIN data d ON DECODE('Y','Y',NULL,a.col) = d.col
You can plug in a variable for the first Y that you set to Y or N (e.g. var_disable_join). This will bypass the join and avoid both the associated performance penalty and the Cartesian product effect. But again, I want to reiterate, this is an advanced hack and is probably NOT what you need. Simply leaving out the unwanted tables it the right approach 95% of the time.

Why do I receive different results in an Access query when the order of the columns is different with a distinct clause?

Exactly as the title says.
I have an MS Access database. I didn't create it, I was handed it with a request to update a query. My task was to add a column with a calculated result, and we added a new column... essentially lets say we have query:
SELECT DISTINCT a, b, c
FROM tbl1
Modified with a UDF to be:
SELECT UDF(d) as e, *
INTO tb2
FROM
(SELECT DISTINCT a, b, c, d FROM tbl1)
We did this, and got different answers, 3 more rows out of hundreds of thousands. I assumed simply that column d must contain more information and after removing duplicates by the DISTINCT clause we ended up with more columns.
In attempting to verify this, we discovered that the order of the columns seemed to matter. If we did this:
SELECT UDF(d) as e, *
INTO tb2
FROM (SELECT DISTINCT a, c, b, d FROM tbl1)
The extra columns went away.
I thought at first that I was using distinct wrong, but checking different syntax combinations resulted in errors, and looking up the SQL documentation for access said that this was correct. A colleague suggested that we needed a GROUP BY clause but since we're not doing any aggregation and we want the globally unique records that doesn't seem to fit.
What am I missing?

Inner join and cross apply. How does it get evaluated?

If Inner join is: For each row in the left table, find row in the right table where the condition is met.
What's is cross apply? I have read that it's just inner join which gets evaluated row by row, but isn't inner join also evaluated row by row?
How do you explain cross apply in plain English? Is it just inner join but allows more complicated joins?
APPLY is different from JOIN in that it allows for correlated subqueries. For instance:
SELECT ...
FROM outer
APPLY (
SELECT ..
FROM inner WHERE outer.column = inner.column
)
At first this does not seems much of a difference, until you consider relational functions. Since APPLY accepts correlations from the other side, it means you can pass it values as arguments to the function:
SELECT ...
FROM outer
APPLY function(outer.column)
This is something not possible with JOIN.
The CROSS vs. OUTER is the same as with JOINs'.
Inner Join (or simply join):
Given 2 tables, A, and B, and a condition C that correlates A and B (most commonly, an equality relation between 2 fields, one from A, and one from B), joining table A with B based on C means that, for each row in A, check for rows in B where C is met - and return them.
Translating it into an example:
SELECT * FROM A inner join B on A.field1 = B.field5
Here, for each row in A, check for rows in B where A's field1 equals B's field5.
Return all such rows.
Cross Join:
A join that is not based on an explicit condition - rather - it combines every row from A with every row from B, and returns such rows.
Assuming A has 10 rows and B 20, you would get a result set of 200 rows.
Cross Apply: (which I have just learned about thanks to you :)
A cross apply is indeed related to a cross join, hence it bears "cross" in its name as well. What happens in a cross apply, as far as I understand, is:
Given a table A, and a function F, for each row selected by a given select statement from A, cross join it with the results of F.
Let's say A has 10 rows, and F is simply a function that returns 3 constant rows, like
1
2
3
For each one of the 10 rows from A, you will cross join the 3 resulting rows from F. Resulting in a result set of 30 rows.
Now, for which purpose was this statement created, I think I can't help much.
What I can think of, after reading some SO threads, is that it provides performance gains in such cross join operations (you could achieve the same results without using a function such as F and the "Cross-Apply").
This post provides an example of a scenario where such performance gain is achieved.

Multiple elements in sub-query

I am trying to write a query in the form of:
SELECT
field_a.table AS x,
field_b.table AS y,
( SELECT
field_a.tableb AS a,
field_b.tableb AS b,
FROM tableb) FROM table
However, I get the following error message: Operand should contain 1 column(s)
Is there any way this can be done or will I have to resort to multiple sub-queries? I just see it as quite inefficient.
Cheers
For your proposed query to make any sense at all, it must be the case that table tableb has only one row. In that case, you can probably achieve your objective with a join instead of a subquery. Maybe this is what you want:
SELECT
table.field_a AS x,
table.field_b AS y,
tableb.field_a AS a,
tableb.field_b AS b
FROM
table CROSS JOIN tableb
If in fact tableb has multiple rows, each correlated in some way with exactly one row of table, then you would instead perform an [INNER] JOIN using a join predicate corresponding to the appropriate relationship. If you want anything more specific then you'll need to describe your data better.

SQL Query Results

I have to write a custom interpreter that simulates SQL select queries on a database with three tables: A, B, and C. My question is as follows: do the following queries return the same results?
select A1
from A
where A1 = 1;
select A1
from A, C
where A1 = 1;
As I have it written, these two provide different results, because of the added table in the from clause. But I'm not sure if that's right; should the results depend on the tables in the from clause or the joins (or lack thereof) in the where clause?
The Second will return all the rows matching de A where Clause and all the row from the C table. Since there is no relation defined between those table. It's often call a cartesian product.
If you want a relation between A and C you will need a join between those, such as A.C_ID = C.ID for a matching pattern, or LEFT | RIGHT join depending on the set of result you want.