简体   繁体   中英

Query design for nested statements and CTEs

I have a query that sequentially joins 6 tables from their original data sources. Nested, it's a mess:

SELECT
FROM
(
    SELECT
    FROM
    (
        SELECT
        FROM
        (. . .)
        INNER JOIN
    )
    INNER JOIN
)

I switched to CTE definitions, and each definition is one join on a previous definition, with the final query at the end providing the result:

WITH
Table1 (field1, field2) AS
(
    SELECT
    FROM 
    INNER JOIN
),

Table2 (field2, field3) AS
(
    SELECT
    FROM Table1
    INNER JOIN
), . . . 

SELECT 
FROM Table 6

This is a lot more readable, and dependencies flow downward in logical order. However, this doesn't seem like the intended use of CTEs (and also why I'm not using Views), since each definition is really only referenced once in order.

Is there any guidance out there on how to construct sequentially nested joins like this that is both readable and logical in structure?

I don't think there is anything wrong in utilizing CTE to create temporary views.

  1. In a larger shop, there are roles defined that separates the responsibility of DBAs versus developers. The CREATE statement, in general, will be the victim of this bureaucracy. Hence, no view. CTE is a very good compromise.
  2. If the views are not really reusable anyway, keeping it with the SQL makes it more readable.
  3. CTE is a lot more readable and intuitive than sub-queries (even with just one level). If your subqueries are not correlated, I would just suggesting converting all of your sub-queries to CTE.
  4. Recursion is the "killer" app for CTE, but it doesn't mean that you shouldn't use CTE, otherwise.

The only con that I can think of is that (depending on your Database Engine) it might confuse or prevent the optimizer from doing what it's suppose to do. Optimizers are smart enough to rewrite subqueries for you.

Now, let us discuss abuse of CTE, be careful that you don't substitute your application developer knowledge for Database Engine optimization. There are a lot of smart developers (smarter that us) that designed this software, just write the query without cte or subqueries as much as possible and let the DB do the work. For example, I often see developers DISTINCT/WHERE every key in a subquery before doing their join. You may think your doing the right thing, but you're not.

With regards to your question, most people intend to solve problems and not discuss something theoretical. Hence, you get people scratching their heads on what you are after. I wouldn't say you didn't imply that in your text, but perhaps be more forceful.

May be I didn't understand the question but what's wrong with:

select * from table1 t1, table2 t2, table3 t3, table4 t4, table5 t5, table6 t6 
where t1.id = t2.id and t2.id = t3.id and  t3.id = t4.id 
  and t4.id = t5.id and t5.id = t6.id

or same using table 1 t1 INNER JOIN table2 t2 ON t1.id = t2.id ....

why didn't you just join your tables like this

select *
from Table1 as t1
    inner join Table2 as t2 on t2.<column> = t1.<column>
    inner join Table3 as t3 on t3.<column> = t2.<column>
    inner join Table4 as t4 on t4.<column> = t3.<column>
    inner join Table5 as t5 on t5.<column> = t4.<column>
    inner join Table6 as t6 on t6.<column> = t5.<column>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM