How to use a table alias with a Union statement in Access? - sql

In an unpivoting operation, I would like the following:
SELECT A, B, C FROM [complex joins/where clause] As DerivedTable
UNION
SELECT A, B, D FROM DerivedTable
UNION
SELECT A, B, E FROM DerivedTable
...
but it complains that DerivedTable cannot be found (I use a derived table so that [complex joins/where clause] doesn't have to be evaluated again and again thereby slowing things).
I know I can simply create a new query called DerivedTable to represent [complex joins/where clause] but
The above SQL is passed from Excel - I'd rather not have to open the database to create a new query prior to running the above
The [complex joins/where clause] is generated dynamically, and changes from user to user, two of which may be running the above SQL at the same time.

Something like this. Use CASE and JOIN this table with (1,2,3,...) table. I'm not sure it is right syntax for Access but it will work on most SQL dialects.
SQLFiddle demo
SELECT A,B,
CASE WHEN CT.r=1 then C
WHEN CT.r=2 then D
WHEN CT.r=3 then E
END
FROM [complex joins/where clause] As DerivedTable
CROSS JOIN (select 1 as r
union all
select 2 as r
union all
select 3 as r
) as CT
order by A,B

Related

How to write a subquery in a select statement in hive

I have the need to write a Hive query that has a subquery in the select statement. Im aware that Hive does not support this, therefore I'm looking out for my options.
select
a,
b,
(select max(tbl.c) from sample_table_a tbl where tbl.d like 'X012%') as d,
e,
f
from sample_table_b
How can I implement the above query in hive without using a cross join because sample_table_a contains about 40000 tuples and so does the sample_table_b.
This could be an option:
There is going to be a single row in table t so join should not be that much a problem
select
a,
b,
max_value,
e,
f
from
sample_table_b
inner join
(
select
max(tbl.c) as max_value
from
sample_table_a tbl
where
tbl.d like 'X012%'
)
t;

Can I select several tables in the same WITH query?

I have a long query with a with structure. At the end of it, I'd like to output two tables. Is this possible?
(The tables and queries are in snowflake SQL by the way.)
The code looks like this:
with table_a as (
select id,
product_a
from x.x ),
table_b as (
select id,
product_b
from x.y ),
table_c as (
..... many more alias tables and subqueries here .....
)
select * from table_g where z = 3 ;
But for the very last row, I'd like to query table_g twice, once with z = 3 and once with another condition, so I get two tables as the result. Is there a way of doing that (ending with two queries rather than just one) or do I have to re-run the whole code for each table I want as output?
One query = One result set. That's just the way that RDBMS's work.
A CTE (WITH statement) is just syntactic sugar for a subquery.
For instance, a query similar to yours:
with table_a as (
select id,
product_a
from x.x ),
table_b as (
select id,
product_b
from x.y ),
table_c as (
select id,
product_c
from x.z ),
select *
from table_a
inner join table_b on table_a.id = table_b.id
inner join table_c on table_b.id = table_c.id;
Is 100% identical to:
select *
from
(select id, product_a from x.x) table_a
inner join (select id, product_b from x.y) table_b
on table_a.id = table_b.id
inner join (select id, product_c from x.z) table_c
on table_b.id = table_c.id
The CTE version doesn't give you any extra features that aren't available in the non-cte version (with the exception of a recursive cte) and the execution path will be 100% the same (EDIT: Please see Simon's answer and comment below where he notes that Snowflake may materialize the derived table defined by the CTE so that it only has to perform that step once should the CTE be referenced multiple times in the main query). As such there is still no way to get a second result set from the single query.
While they are the same syntactically, they don't have the same performance plan.
The first case can be when one of the stages in the CTE is expensive, and is reused via other CTE's or join to many times, under Snowflake, use them as a CTE I have witness it running the "expensive" part only a single time, which can be good so for example like this.
WITH expensive_select AS (
SELECT a.a, b.b, c.c
FROM table_a AS a
JOIN table_b AS b
JOIN table_c AS c
WHERE complex_filters
), do_some_thing_with_results AS (
SELECT stuff
FROM expensive_select
WHERE filters_1
), do_some_agregation AS (
SELECT a, SUM(b) as sum_b
FROM expensive_select
WHERE filters_2
)
SELECT a.a
,a.b
,b.stuff
,c.sum_b
FROM expensive_select AS a
LEFT JOIN do_some_thing_with_results AS b ON a.a = b.a
LEFT JOIN do_some_agregation AS c ON a.a = b.a;
This was originally unrolled, and the expensive part was some VIEWS that the date range filter that was applied at the top level were not getting pushed down (due to window functions) so resulted in full table scans, multiple times. Where pushing them into the CTE the cost was paid once. (In our case putting date range filters in the CTE made Snowflake notice the filters and push them down into the view, and things can change, a few weeks later the original code ran as good as the modified, so they "fixed" something)
In other cases, like this the different paths that used the CTE use smaller sub-sets of the results, so using the CTE reduced the remote IO so improved performance, there then was more stalls in the execution plan.
I also use CTEs like this to make the code easier to read, but giving the CTE a meaningful name, but the aliasing it to something short, for use. Really love that.

Modify: Query which uses Group By/Having clauses, to another query which uses just Select/From/Where

Can a query which uses Group By/Having clauses, be modified to another query which uses just Select/From/Where clauses?
TABLE T(a, b, c)
SELECT a, sum(c)
FROM T
WHERE b>10
GROUP BY a
HAVING sum(c)>5
Would appreciate it if you could explain in detail why it can(not) be done.
You could, of course, resort to using window functions only, if your specific database supports those:
SELECT a, s
FROM (
SELECT DISTINCT a, sum(c) OVER (PARTITION BY a) s
FROM t1
WHERE b > 10
) t2
WHERE s > 5
Another option is to use correlated subqueries, which work on all databases:
SELECT a, s
FROM (
SELECT DISTINCT a, (SELECT sum(c) FROM t t3 WHERE t1.a = t3.a AND b > 10) s
FROM t t1
WHERE b > 10
) t2
WHERE s > 5
These alternatives would yield the same result without using GROUP BY or HAVING. But either of these would be (much) slower, and I don't really see the point...

Multiple reusable SQL queries

(Note I am getting an error submitting to stackoverflow if i use "select", so have misspelled my queries. [Now Fixed])
Sorry this is a newbie question. I have one very long SQL query that is getting harder to manage. In fact there are some sub-queries that are being used multiple times. What is the best way to break up the query? I would prefer to keep it in the database, rather than take it out into the calling program. It goes something like this.
Select A, B, C
from (select D from Table_1 where ...)
Union Select E, F
from Table_2
Inner Join (Select D, E, from Table_1 where...)..
So what I would like to do is
Result1 = select D,E from Table_1 where....
Result2 = Select A,B,C from Result_1 Union Select E,F from Table_2 Inner Join Result_1 ...
What is the best way to do this? I can't use Views because I don't have privileges. How can I use the results from the first query in the second query? Can cursors be used in this case?
Using a CTE you can access the same subquery multiple times (this is the main difference to Derived Tables):
with CTE as
(Select D, E, from Table_1 where...)
Select A, B, C
from CTE
Union
Select E, F
from Table_2
Inner Join CTE ..

SQL Subquery w/LEFT JOIN causing Invalid Object Error

I have a query with the following structure:
EDIT Original structure of the query wasn't quite representative.
SELECT A
,B
,C
,D
FROM ( SELECT id,A
FROM myTable
WHERE conditions
GROUP BY id,A) MainQuery
LEFT JOIN (SELECT id, B, C
FROM myView
WHERE id IN
(
SELECT DISTINCT id
FROM MainQuery
)
) sub1
ON sub1.B = MainQuery.A
LEFT JOIN (SELECT MainQuery.id, D
FROM myOtherView
WHERE sub1.id IN
(
SELECT DISTINCT id
FROM MainQuery
)
) sub2
ON sub2.D = sub1.C
When I run the query, I get the error message Invalid object name 'MainQuery'. When I comment out the LEFT JOINs and the fields they feed in the SELECT statement, the query runs just fine. I've also tried AS MainQuery, but I get the same result.
I suspect it has something to do with scope. Where I'm trying to SELECT DISTINCT id FROM MainQuery, is MainQuery out of scope for the WHERE subquery within sub1?
For context, I've been tasked with rewriting a query that used temp tables into a query that can be used in a report deployed on SSRS 2000. My MainQuery, sub1, and sub2 were temp tables in the original query. Those temp tables used subqueries within them, which I've preserved in my translation. But the original query had the advantage of creating each temp table separately, and then joining the results. Temp tables and subqueries are new to me, so I'm not sure how to adapt between the two, or if that's even the right approach.
The SQL for your MainQuery is invalid. Run it by itself and see:
SELECT A, id
FROM myTable
WHERE conditions
GROUP BY A
You can't select A and id, but only group by A. Either you need to also group by id, or wrap id in an aggregate function like min, or max.
With that addressed it looks like your other issue is that you say "LEFT JOIN" but then place the column of your LEFT JOINED table on the left hand side of your where clause. See below where I flip sub1.B and MainQuery.A in the JOIN.
SELECT A
,B
,C
,D
FROM ( SELECT A, id
FROM myTable
WHERE conditions
GROUP BY A,id) MainQuery
LEFT JOIN nutherTable sub1
on MainQuery.A = sub1.B
and MainQuery.id = sub1.id
LEFT JOIN (SELECT D ...) sub2
ON sub1.C = sub2.D