Repository: sqlfluff/sqlfluff

Issue:
L027: outer-level table not found in WHERE clause sub-select
### Search before asking

- [X] I searched the [issues](https://github.com/sqlfluff/sqlfluff/issues) and found no similar issues.


### What Happened

Outer-level table/view referenced in sub-select inside `WHERE` clause is not being detected.

This error seems to only occur when the sub-select contains joins.

### Expected Behaviour

No error

### Observed Behaviour

```
L:   7 | P:  32 | L027 | Qualified reference 'my_table.kind' not found in
                       | available tables/view aliases ['other_table',
                       | 'mapping_table'] in select with more than one referenced
                       | table/view.
```

### How to reproduce

```sql
SELECT my_col
FROM my_table
WHERE EXISTS (
    SELECT 1
    FROM other_table
    INNER JOIN mapping_table ON (mapping_table.other_fk = other_table.id_pk)
    WHERE mapping_table.kind = my_table.kind
);
```

### Dialect

postgres

### Version

sqlfluff, version 0.12.0

### Configuration

```
[sqlfluff]
nocolor = True
dialect = postgres
```

### Are you willing to work on and submit a PR to address the issue?

- [ ] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/sqlfluff/sqlfluff/blob/main/CODE_OF_CONDUCT.md)



Discussion:
Does L027 use `SelectCrawler`? This sounds like an issue where it may be helpful.

Related: Rules that use `SelectCrawler` may be good candidates to benefit from setting `recurse_into` to `False`. (Setting the flag is just a start. This also requires reworking the rule code, hopefully no more than 1-2 hours of work.)
Answering my own question: It does not seem to use `SelectCrawler`. Rules that currently use it:
* L025
* L026
* L044
* L045

From a quick look at the YML test files for each of these rules, I suggest L044 would be the best one to review in terms of handling similar requirements. Look for test cases that mention "subquery".
I think a very similar fix to that implemented in this [PR for L028](https://github.com/sqlfluff/sqlfluff/pull/3156) will also work here. In particular, notice the code that looks at `query.parent` to find tables that are "visible" to a particular query.

https://github.com/sqlfluff/sqlfluff/blob/main/src/sqlfluff/rules/L028.py#L108L114
Related to #3380, possibly duplicate

Patch:
diff --git a/src/sqlfluff/rules/L027.py b/src/sqlfluff/rules/L027.py
--- a/src/sqlfluff/rules/L027.py
+++ b/src/sqlfluff/rules/L027.py
@@ -99,23 +99,6 @@ def _lint_references_and_aliases(
                     )
                 )
 
-            all_table_aliases = [t.ref_str for t in table_aliases] + standalone_aliases
-
-            # For qualified references, we want to check that the alias is actually
-            # valid
-            if (
-                this_ref_type == "qualified"
-                and list(r.iter_raw_references())[0].part not in all_table_aliases
-            ):
-                violation_buff.append(
-                    LintResult(
-                        anchor=r,
-                        description=f"Qualified reference {r.raw!r} not found in "
-                        f"available tables/view aliases {all_table_aliases} in select "
-                        "with more than one referenced table/view.",
-                    )
-                )
-
         return violation_buff or None
 
     def _init_ignore_words_list(self):


Test patch:
diff --git a/test/fixtures/rules/std_rule_cases/L027.yml b/test/fixtures/rules/std_rule_cases/L027.yml
--- a/test/fixtures/rules/std_rule_cases/L027.yml
+++ b/test/fixtures/rules/std_rule_cases/L027.yml
@@ -221,43 +221,6 @@ test_pass_rowtype_with_join:
     core:
       dialect: hive
 
-test_fail_column_name_not_found_in_table_aliases_bigquery:
-  # qualified reference should actually exists in table aliases
-  fail_str: |
-    SELECT
-        a.bar,
-        b.foo,
-        this_is.some_struct.id
-    FROM
-        a LEFT JOIN b ON TRUE
-  configs:
-    core:
-      dialect: bigquery
-
-test_pass_column_name_is_a_struct_bigquery:
-  # check structs work as expected
-  pass_str: |
-    SELECT
-        a.bar,
-        b.this_is.some_struct.id
-    FROM
-        a LEFT JOIN b ON TRUE
-  configs:
-    core:
-      dialect: bigquery
-
-test_pass_column_name_from_unnest_bigquery:
-  # Check that we allow an table alias come from UNNEST statement
-  pass_str: |
-    SELECT
-        a.bar,
-        e.foo
-    FROM
-        a LEFT JOIN UNEST(a.events) AS e
-  configs:
-    core:
-      dialect: bigquery
-
 test_fail_table_plus_flatten_snowflake_1:
   # FLATTEN() returns a table, thus there are two tables, thus lint failure.
   fail_str: |
@@ -328,3 +291,48 @@ test_pass_ignore_words_regex_bigquery_declare_example:
     rules:
       L027:
         ignore_words_regex: ^_
+
+test_pass_redshift:
+  # This was failing in issue 3380.
+  pass_str:
+    SELECT account.id
+    FROM salesforce_sd.account
+    INNER JOIN salesforce_sd."user" ON salesforce_sd."user".id = account.ownerid
+  configs:
+    core:
+      dialect: redshift
+
+test_pass_tsql:
+  # This was failing in issue 3342.
+  pass_str:
+    select
+        psc.col1
+    from
+        tbl1 as psc
+    where
+        exists
+        (
+            select 1 as data
+            from
+                tbl2 as pr
+            join tbl2 as c on c.cid = pr.cid
+            where
+                c.col1 = 'x'
+                and pr.col2 <= convert(date, getdate())
+                and pr.pid = psc.pid
+        )
+  configs:
+    core:
+      dialect: tsql
+
+test_pass_ansi:
+  # This was failing in issue 3055.
+  pass_str: |
+    SELECT my_col
+    FROM my_table
+    WHERE EXISTS (
+        SELECT 1
+        FROM other_table
+        INNER JOIN mapping_table ON (mapping_table.other_fk = other_table.id_pk)
+        WHERE mapping_table.kind = my_table.kind
+    )
diff --git a/test/rules/std_test.py b/test/rules/std_test.py
--- a/test/rules/std_test.py
+++ b/test/rules/std_test.py
@@ -68,7 +68,7 @@
         ),
         ("L016", "block_comment_errors_2.sql", [(1, 85), (2, 86)]),
         # Column references
-        ("L027", "column_references.sql", [(1, 8), (1, 11)]),
+        ("L027", "column_references.sql", [(1, 8)]),
         ("L027", "column_references_bare_function.sql", []),
         ("L026", "column_references.sql", [(1, 11)]),
         ("L025", "column_references.sql", [(2, 11)]),