Is possible to reuse subqueries?
You can take the aggregations out into a CTE (common table expression):
with minima as (select t.id, t.type, min(value) min_value
from table2 t
where t.type in (1,2,3,4)
group by t.id, t.type)
select a.id, a.name,
(select min_value from minima where minima.id = subquery.id and minima.type = 1) as column1,
(select min_value from minima where minima.id = subquery.id and minima.type = 2) as column2,
(select min_value from minima where minima.id = subquery.id and minima.type = 3) as column3,
(select min_value from minima where minima.id = subquery.id and minima.type = 4) as column4
from (select distinct id from table2 t where t.type in (1,2,3,4) and t.value between '2010-01-01' and '2010-01-07') as subquery
left join a on a.id = subquery.id
Whether this is actually any benefit (or even supported) or not depends on your environment and dataset, of course.
Another approach:
select xx.id, a.name, xx.column1, xx.column2, xx.column3, xx.column4
from (
select id,
max(case type when 1 then min_value end) as column1,
max(case type when 2 then min_value end) as column2,
max(case type when 3 then min_value end) as column3,
max(case type when 4 then min_value end) as column4
from (select t.id, t.type, min(value) min_value
from table2 t
where t.type in (1,2,3,4)
group by t.id, t.type) minima
group by id
) xx left join a on a.id = xx.id
order by 1
How to reuse a sub query in sql?
Use a Common Table Expression (CTE) if you're using SQL Server 2005+:
with cte as (
select columns
from result_set
where condition_common
)
select columns
from cte as subset1
join
cte as subset2
on subset1.somekey = subset2.somekey
where otherconditions
How can I reuse a subquery inside a select expression?
The subquery can be reused by introducing intermediate projection (Select
), which is the equivalent of let
operator in the query syntax.
For instance:
dbContext.Organizations.AsNoTracking()
// intermediate projection
.Select(x => new
{
Organization = x,
Owner = x.Members
.Where(member => member.Role == RoleType.Owner)
.OrderBy(member => member.CreatedAt)
.FirstOrDefault()
})
// final projection
.Select(x => new OrganizationListItem
{
Id = x.Organization.Id,
Name = x.Organization.Name,
OwnerFirstName = Owner.FirstName,
OwnerLastName = Owner.LastName,
OwnerEmailAddress = Owner.EmailAddress
})
Note that in pre EF Core 3.0 you have to use FirstOrDefault
instead of First
if you want to avoid client evaluation.
Also this does not make the generated SQL query better/faster - it still contains separate inline subquery for each property included in the final select. Hence will improve readability, but not the efficiency.
That's why it's usually better to project nested object into unflattened DTO property, i.e. instead of OwnerFirstName
, OwnerLastName
, OwnerEmailAddress
have a class with properties FirstName
, LastName
, EmailAddress
and property let say Owner
of that type in OrganizationListItem
(similar to entity with reference navigation property). This way you will be able to use something like
dbContext.Organizations.AsNoTracking()
.Select(x => new
{
Id = x.Organization.Id,
Name = x.Organization.Name,
Owner = x.Members
.Where(member => member.Role == RoleType.Owner)
.OrderBy(member => member.CreatedAt)
.Select(member => new OwnerInfo // the new class
{
FirstName = member.FirstName,
LastName = member.LastName,
EmailAddress = member.EmailAddress
})
.FirstOrDefault()
})
Unfortunately in pre 3.0 versions EF Core will generate N + 1 SQL queries for this LINQ query, but in 3.0+ it will generate a single and quite efficient SQL query.
Reuse of a field from a joined table inside a subquery in FROM clause
Recall SQL's logical order of operations that differ from its lexical order (i.e., order in how it is written). Usually the first step in query processing is the FROM
clause, then JOIN
, ON
, WHERE
, GROUP BY
, etc. and usually ending with ORDER BY
and SELECT
(ironically one of the last clauses processed though written first).
Technically, your queries do not involve correlated subqueries since there are no inner or outer levels. Specifically, the derived table t3
and base table t4
are at the same level. The query engine evaluates t3
in isolation by itself during FROM
clause step. Then, it evaluates JOIN
table, t4
, in isolation by itself and finally applies the matching ON
logic.
Because t4
is not defined in the universe of t3
, MS Access via GUI prompts for that parameter value (where MS Access via ODBC will raise an error). To resolve you have to include all necessary data sources in each table scope:
SELECT t1.field1, t1.field2 - IIF(t3.calcfield IS NULL, 0, t3.calc) As Diff
FROM
(SELECT t2.fieldid, SUM(t2.field3) AS fsum
FROM t2
INNER JOIN table4 sub_t4
ON t2.fieldid = sub_t4.fieldid
WHERE t2.date > sub_t4.date
GROUP BY t2.fieldid
) t3
LEFT JOIN table4 t4
ON t3.fieldid = t4.fieldid
Often, too, using layered queries is beneficial in Access and can help with final, compact queries:
t3
query (save below as a query object)
SELECT t2.fieldid, SUM(t2.field3) AS fsum
FROM t2
INNER JOIN table4 sub_t4
ON t2.fieldid = sub_t4.fieldid
WHERE t2.date > sub_t4.date
GROUP BY t2.fieldid
Final query (join saved query)
SELECT t1.field1, t1.field2 - IIF(t3.calcfield IS NULL, 0, t3.calc) As Diff
FROM my_saved_query t3
LEFT JOIN table4 t4
ON t3.fieldid = t4.fieldid
How to reuse a subquery
Subquery factoring (aka CTEs in other database platforms) is what you need, eg:
with dataset as (select datasetid
from Reportingdatasetmembers
where ReportingDatasetID = param_in_ReportingDataSetID)
select ...
from some_table_1
where ...
and datasetid in (select datasetid from dataset)
union all
select ...
from some_table_2
where ...
and datasetid in (select datasetid from dataset);
Is there a way to reuse subqueries in the same query?
Does WITH help? That lets you define a result set you can use multiple times in the SELECT
.
From their example:
WITH orderable_items (product_id, quantity) AS
( SELECT stocked.product_id, stocked.quantity
FROM stocked, product
WHERE stocked.product_id = product.product_id
AND product.on_hand > 5
)
SELECT product_id, quantity
FROM orderable_items
WHERE quantity < 10;
SQL Server reuse aliases in subqueries
I think that following script can explain you everything.
SELECT 1,1,GETDATE()
INSERT INTO @t ( Id, UserId, TranDate )
SELECT 2,1,GETDATE()
INSERT INTO @t ( Id, UserId, TranDate )
SELECT 3,1,GETDATE()
SELECT tx.Id/*main alias*/,
tx1.Id /*First subquery alias*/,
tx2.Id /*Second subquery alias*/,
(SELECT Id FROM @t txs /*alias only in this one subquery/must be different from main if you want use main alias in it...*/
WHERE txs.Id = tx.Id+2 /*here is used main value = subquery value+2*/) AS Id
FROM @t tx /*main*/
JOIN (SELECT *
FROM @t tx
WHERE tx.Id = 1 /*this one using subquery values + you are not able to use here main value*/
) tx1 --alias of subquery
ON tx.Id = tx1.Id /*here is used main value = subquery value*/
CROSS APPLY (SELECT TOP 1 *
FROM @t txc /*This one must be different from main if you want use it to comparison with main*/
WHERE txc.Id > tx.Id /*this one using subquery value > main value*/
) tx2 --alias of subquery
WHERE tx.Id = 1 AND /*Subquery alias canot reference on First subquery value*/
tx1.Id = 1 AND/*Subquery alias*/
tx2.Id = 2 /*Subquery alias*/
It means that yea, it could be reused, but only if you dont want compare main / sub, because if you reuse it and for example you try to do folowing statement in subquery tx.Id > tx.Id
It causes that only values in subquery will be compared. In our example it causes that you dont get anything because you comaring values in same row...
Related Topics
How to Run a SQL Plus Script in Powershell
Finding Free Slots in a Booking System
SQL Count* Group by Bigger Than,
Does SQL Server Allow Constraint Violations in a Transaction as Long as It's Not Committed Yet
How to Create a Blank/Hardcoded Column in a SQL Query
Extract Data from Xml Clob Using SQL from Oracle Database
T-SQL Conditional Where Clause
SQL Joining Three Tables, Join Precedence
SQL Server Index - Any Improvement for Like Queries
How to Persist a Variable Across a Go
Combine Two Select Queries in Postgresql
How to Copy Indexes from One Table to Another in SQL Server
Sql: Subtracting 1 Day from a Timestamp Date
Convert 24 Hour Time to 12 Hour Plus Am/Pm Indication Oracle SQL
Standard Use of 'Z' Instead of Null to Represent Missing Data