Combine two queries, one based upon the other, into one - sql

I have two queries, one based partly on the other. Is there a way of combining them into a single query?
SELECT tblIssues.*, tblIssues.NewsletterLookup
FROM tblIssues
WHERE (((tblIssues.NewsletterLookup)=5));
SELECT tblArea.ID, tblArea.AreaName
FROM tblArea LEFT JOIN Query2 ON tblArea.ID = Query2.[AreaLookup]
WHERE (((tblArea.Dormant)=False) AND ((Query2.tblIssues.NewsletterLookup) Is Null));

If you want to do this in a single query without Query2, you can use the equivalent SQL from Query2 as a subquery in your second example:
SELECT a.ID, a.AreaName
FROM
tblArea AS a
LEFT JOIN
(
SELECT i.*
FROM tblIssues AS i
WHERE i.NewsletterLookup=5
) AS sub
ON a.ID = sub.[AreaLookup]
WHERE
a.Dormant=False
AND sub.NewsletterLookup Is Null;

You ment to perform a JOIN like
SELECT ti.*, tblArea.ID, tblArea.AreaName
FROM tblArea ta
LEFT JOIN tblIssues ti ON ta.ID = ti.[AreaLookup]
WHERE (ti.NewsletterLookup=5 OR ti.NewsletterLookup Is Null)
AND ta.Dormant=False;

Related

Oracle compare query results with multiple joins against a table

I need to compare query results against a table. I have the following query.
select
i.person_id,
a.appellant_first_name,
a.appellant_middle_name,
a.appellant_last_name,
s.*
from CWLEGAL.individuals i inner join CWLEGAL.tblappealsdatarevisionone a
on i.casenm = a.D_N_NUMBER1 and
i.first_name = a.appellant_first_name and
i.last_name = a.appellant_last_name
inner join CWLEGAL.tblappealstosupremecourt s
on a.DATABASEIDNUMBER = s.DBIDNUMBER
order by orclid21;
I need to see what orclid21's in cwlegal.tblappealstosupremecourt don't appear in the above query.
I was able to get this to work.
select
i.person_id,
a.appellant_first_name,
a.appellant_middle_name,
a.appellant_last_name,
s.*
from CWLEGAL.tblappealstosupremecourt s
join CWLEGAL.tblappealsdatarevisionone a
on a.DATABASEIDNUMBER = s.DBIDNUMBER
left outer join CWLEGAL.individuals i on
i.casenm = a.D_N_NUMBER1 and
i.first_name = a.appellant_first_name and
i.last_name = a.appellant_last_name
where person_id is null
order by orclid21
You are making the first inner join between i and a, the result of which you're joining with s.
Now, if you want to see which records won't join, that's known as anti-join, and in whatever database you're querying it, it may be achieved by either selecting a null result or taking those records as a new result.
Examples, with taking your query (the whole code in the question) as q, assuming you've kept all the needed keys in it:
Example 1:
with your_query as q
select s.orclid21 from q
left join CWLEGAL.tblappealstosupremecourt s
on q.DATABASEIDNUMBER = s.DBIDNUMBER
and s.orclid21 is null
Example 2:
with your_query as q
select s.orclid21 from q
right join CWLEGAL.tblappealstosupremecourt s
on q.DATABASEIDNUMBER != s.DBIDNUMBER
Example 3:
with your_query as q
select s.orclid21 from CWLEGAL.tblappealstosupremecourt s
where s.DBIDNUMBER not in (select distinct q.DATABASEIDNUMBER from q)

SQL Intersect not supported in Phoenix , alternative for intersect in phoenix?

I have the following SQL expression:
SELECT SS_ITEM_SK AS POP_ITEM_SK
FROM (SELECT SS_ITEM_SK
FROM (SELECT SS_ITEM_SK,(ITEM_SOLD-ITEM_RETURNED) AS TOT_SOLD_QTY FROM (SELECT SS_ITEM_SK,COUNT(SS_ITEM_SK) AS ITEM_SOLD,COUNT(SR_ITEM_SK) AS ITEM_RETURNED FROM STORE_SALES1 right outer join STORE_RETURNS1 on SS_TICKET_NUMBER = SR_TICKET_NUMBER AND SS_ITEM_SK = SR_ITEM_SK GROUP BY SS_ITEM_SK)))
INTERSECT
SELECT CS_ITEM_SK AS POP_ITEM_SK FROM (SELECT CS_ITEM_SK
FROM (SELECT CS_ITEM_SK,(ITEM_SOLD-ITEM_RETURNED) AS TOT_SOLD_QTY FROM (SELECT CS_ITEM_SK,COUNT(CS_ITEM_SK) AS ITEM_SOLD,COUNT(CR_ITEM_SK) AS ITEM_RETURNED FROM CATALOG_SALES1 right outer join CATALOG_RETURNS1 on CS_ORDER_NUMBER = CR_ORDER_NUMBER and CS_ITEM_SK = CR_ITEM_SK GROUP BY CS_ITEM_SK)))
INTERSECT
SELECT WS_ITEM_SK AS POP_ITEM_SK FROM (SELECT WS_ITEM_SK
FROM (SELECT WS_ITEM_SK,(ITEM_SOLD-ITEM_RETURNED) AS TOT_SOLD_QTY FROM (SELECT WS_ITEM_SK,COUNT(WS_ITEM_SK) AS ITEM_SOLD,COUNT(WR_ITEM_SK) AS ITEM_RETURNED FROM WEB_SALES1 right outer join WEB_RETURNS1 on WS_ORDER_NUMBER = WR_ORDER_NUMBER AND WS_ITEM_SK = WR_ITEM_SK GROUP BY WS_ITEM_SK)))
Apache phoenix is not supporting the keyword INTERSECT. Can somebody please help me to correct above query without using INTERSECT?
I think there are multiple ways you can do this:
Join Method
select * from ((query1 inner join query2 on column_names) inner join query3 on column_names)
Exists Method
(query1 where exists (query2 where exists (query3)) )
In Method
(query1 where column_name in (query2 where column_name in (query3)) )
References: https://blog.jooq.org/2015/10/06/you-probably-dont-use-sql-intersect-or-except-often-enough/
and http://phoenix.apache.org/subqueries.html
Although I would use the exists/in over the join since if these queries return huge data then you might have to optimize your queries using this:
https://phoenix.apache.org/joins.html

Is there a way to make multiple UNION's more efficient when they all do the same joins?

I have 3 tables and I'd like to make a view that aggregates data vertically (using UNIONS) from the 3 tables. I already have a query that does what I want, but it uses a lot of repeated joins for each query, and I'm wondering if there is a way to only join up all these tables once and put the unions on top of that.
I want to join 3 tables that I will call desiredTable1, desiredTable2, and desiredTable3.
They all make use of joins on joinTable, joinTable2 and joinTable3 like so:
(select desiredTable1.id, desiredTable1.created_at, joinTable1.firstname, joinTable1.lastname, 'DESCRIPTOR_1' as "descriptor", desiredTable1.amount from desiredTable1
join joinTable3 on joinTable3.id = desiredTable1.joinTable3_id
join joinTable2 on joinTable2.id = joinTable3.joinTable2_id
join joinTable1 on joinTable1.id = joinTable2.joinTable1_id)
UNION
(select desiredTable2.id, desiredTable2.created_at, joinTable1.firstname, joinTable1.lastname, 'DESCRIPTOR_2' as "descriptor", desiredTable2.amount from desiredTable2
join joinTable3 on joinTable3.id = desiredTable2.joinTable3_id
join joinTable2 on joinTable2.id = joinTable3.joinTable2_id
join joinTable1 on joinTable1.id = joinTable2.joinTable1_id)
UNION
(select desiredTable3.id, desiredTable3.created_at, joinTable1.firstname, joinTable1.lastname, 'DESCRIPTOR_3' as "descriptor", desiredTable3.amount from desiredTable3
join joinTable3 on joinTable3.id = desiredTable3.joinTable3_id
join joinTable2 on joinTable2.id = joinTable3.joinTable2_id
join joinTable1 on joinTable1.id = joinTable2.joinTable1_id)
As you can see, I need the linked information from joinTable1 in each query, but if I can help it, I would prefer not to repeat all these joins. Is there a way I could "define" a subquery that does all those joins, then do all the unions on top of that?
You can use union all before joining:
select dt.id, dt.created_at, jt1.firstname, jt1.lastname, dt.descriptor, dt.amount
from ((select dt1.*, 'DESCRIPTOR_1' as descriptor
from desiredTable1 dt1
) union all
(select dt2.*, 'DESCRIPTOR_2' as descriptor
from desiredTable2 dt2
) union all
(select dt3.*, 'DESCRIPTOR_3' as descriptor
from desiredTable3 dt3
)
) dt join
joinTable3 jt3
on jt3.id = dt.joinTable3_id join
joinTable2 jt2
on jt2.id = jt3.joinTable2_id join
joinTable1 jt1
on jt1.id = jt2.joinTable1_id;
Note: This uses dt.* for the subqueries as a convenience. If the tables don't have the same columns, list only the ones needed for the outer query.

select columns from different tables with different data type columns

I want to know how to write a query, which selects specific columns(not common) from 2 different tables and combine them together.
I tried this, but didn't work:
SELECT ii.sequence
FROM Costs ii
WHERE ii.order_ID IN (SELECT book.order_ID
FROM BookInfo ci
WHERE ii.order_ID = ci.order_ID)
UNION
SELECT ft.released_title
FROM FinishedBook ft
WHERE ft.version IN (SELECT ii.iiversion
FROM Costs ii
WHERE ii.iiorder_ID IN (SELECT ci.order_ID
FROM BookInfo ci
WHERE ii.iiorder_ID = ci.order_ID))
ORDER BY sequence;
Isn't this a case of joining these tables and calling Distinct to avoid duplicates?
Try this:
select Distinct a.Sequence, b.RELEASED_TITLE
from IncludedIn a inner join FinishedTrack b
on a.OriginatesFrom = b.IIOriginatesFrom
Inner join CdInfo c on a.IIALBUM_ID = c.ALBUM_ID
Order By a.Sequence
For MSSQL Server, Use Join to get the result.
SELECT I.Sequence, F.Released_Title FROM FinishedTrack AS F
INNER JOIN IncludedIn AS I ON I.ORIGINATESFROM = F.IIORIGINATESFROM
INNER JOIN CdInfo AS A ON A.ALBUM_ID = I.IIALBUM_ID
ORDER BY I.Sequence DESC
You need to use a JOIN instead of a UNION:
SELECT ii.sequence, ft.released_title
FROM IncludedIn ii
INNER JOIN CdInfo ci ON ii.iialbumid = ci.album_id
INNER JOIN FinishedTrack ft on ft.originatesfrom = ii.iioriginatesfrom
ORDER BY ii.sequence;
This query might work for you
SELECT IncludedIn.SEQUENCE, FinishedTrack.RELEASED_TITLE
FROM FinishedTrack
INNER JOIN IncludedIn
ON FinishedTrack.ORIGINATESFROM=IncludedIn.IIORIGINATESFROM and
FinishedTrack.VERSION=IncludedIn.IIVERSION order by FinishedTrack.SEQUENCE;

Recursive query with outer joins?

I'm attempting the following query,
DECLARE #EntityType varchar(25)
SET #EntityType = 'Accessory';
WITH Entities (
E_ID, E_Type,
P_ID, P_Name, P_DataType, P_Required, P_OnlyOne,
PV_ID, PV_Value, PV_EntityID, PV_ValueEntityID,
PV_UnitValueID, PV_UnitID, PV_UnitName, PV_UnitDesc, PV_MeasureID, PV_MeasureName, PV_UnitValue,
PV_SelectionID, PV_DropDownID, PV_DropDownName, PV_DropDownOptionID, PV_DropDownOptionName, PV_DropDownOptionDesc,
RecursiveLevel
)
AS
(
-- Original Query
SELECT dbo.Entity.ID AS E_ID, dbo.EntityType.Name AS E_Type,
dbo.Property.ID AS P_ID, dbo.Property.Name AS P_Name, DataType.Name AS P_DataType, Required AS P_Required, OnlyOne AS P_OnlyOne,
dbo.PropertyValue.ID AS PV_ID, dbo.PropertyValue.Value AS PV_Value, dbo.PropertyValue.EntityID AS PV_EntityID, dbo.PropertyValue.ValueEntityID AS PV_ValueEntityID,
dbo.UnitValue.ID AS PV_UnitValueID, dbo.UnitOfMeasure.ID AS PV_UnitID, dbo.UnitOfMeasure.Name AS PV_UnitName, dbo.UnitOfMeasure.Description AS PV_UnitDesc, dbo.Measure.ID AS PV_MeasureID, dbo.Measure.Name AS PV_MeasureName, dbo.UnitValue.UnitValue AS PV_UnitValue,
dbo.DropDownSelection.ID AS PV_SelectionID, dbo.DropDown.ID AS PV_DropDownID, dbo.DropDown.Name AS PV_DropDownName, dbo.DropDownOption.ID AS PV_DropDownOptionID, dbo.DropDownOption.Name AS PV_DropDownOptionName, dbo.DropDownOption.Description AS PV_DropDownOptionDesc,
0 AS RecursiveLevel
FROM dbo.Entity
INNER JOIN dbo.EntityType ON dbo.EntityType.ID = dbo.Entity.TypeID
INNER JOIN dbo.Property ON dbo.Property.EntityTypeID = dbo.Entity.TypeID
INNER JOIN dbo.PropertyValue ON dbo.Property.ID = dbo.PropertyValue.PropertyID AND dbo.PropertyValue.EntityID = dbo.Entity.ID
INNER JOIN dbo.DataType ON dbo.DataType.ID = dbo.Property.DataTypeID
LEFT JOIN dbo.UnitValue ON dbo.UnitValue.ID = dbo.PropertyValue.UnitValueID
LEFT JOIN dbo.UnitOfMeasure ON dbo.UnitOfMeasure.ID = dbo.UnitValue.UnitOfMeasureID
LEFT JOIN dbo.Measure ON dbo.Measure.ID = dbo.UnitOfMeasure.MeasureID
LEFT JOIN dbo.DropDownSelection ON dbo.DropDownSelection.ID = dbo.PropertyValue.DropDownSelectedID
LEFT JOIN dbo.DropDownOption ON dbo.DropDownOption.ID = dbo.DropDownSelection.SelectedOptionID
LEFT JOIN dbo.DropDown ON dbo.DropDown.ID = dbo.DropDownSelection.DropDownID
WHERE dbo.EntityType.Name = #EntityType
UNION ALL
-- Recursive Query?
SELECT E2.E_ID AS E_ID, dbo.EntityType.Name AS E_Type,
dbo.Property.ID AS P_ID, dbo.Property.Name AS P_Name, DataType.Name AS P_DataType, Required AS P_Required, OnlyOne AS P_OnlyOne,
dbo.PropertyValue.ID AS PV_ID, dbo.PropertyValue.Value AS PV_Value, dbo.PropertyValue.EntityID AS PV_EntityID, dbo.PropertyValue.ValueEntityID AS PV_ValueEntityID,
dbo.UnitValue.ID AS PV_UnitValueID, dbo.UnitOfMeasure.ID AS PV_UnitID, dbo.UnitOfMeasure.Name AS PV_UnitName, dbo.UnitOfMeasure.Description AS PV_UnitDesc, dbo.Measure.ID AS PV_MeasureID, dbo.Measure.Name AS PV_MeasureName, dbo.UnitValue.UnitValue AS PV_UnitValue,
dbo.DropDownSelection.ID AS PV_SelectionID, dbo.DropDown.ID AS PV_DropDownID, dbo.DropDown.Name AS PV_DropDownName, dbo.DropDownOption.ID AS PV_DropDownOptionID, dbo.DropDownOption.Name AS PV_DropDownOptionName, dbo.DropDownOption.Description AS PV_DropDownOptionDesc,
(RecursiveLevel + 1)
FROM Entities AS E2
INNER JOIN dbo.Entity ON dbo.Entity.ID = E2.PV_ValueEntityID
INNER JOIN dbo.EntityType ON dbo.EntityType.ID = dbo.Entity.TypeID
INNER JOIN dbo.Property ON dbo.Property.EntityTypeID = dbo.Entity.TypeID
INNER JOIN dbo.PropertyValue ON dbo.Property.ID = dbo.PropertyValue.PropertyID AND dbo.PropertyValue.EntityID = E2.E_ID
INNER JOIN dbo.DataType ON dbo.DataType.ID = dbo.Property.DataTypeID
INNER JOIN dbo.UnitValue ON dbo.UnitValue.ID = dbo.PropertyValue.UnitValueID
INNER JOIN dbo.UnitOfMeasure ON dbo.UnitOfMeasure.ID = dbo.UnitValue.UnitOfMeasureID
INNER JOIN dbo.Measure ON dbo.Measure.ID = dbo.UnitOfMeasure.MeasureID
INNER JOIN dbo.DropDownSelection ON dbo.DropDownSelection.ID = dbo.PropertyValue.DropDownSelectedID
INNER JOIN dbo.DropDownOption ON dbo.DropDownOption.ID = dbo.DropDownSelection.SelectedOptionID
INNER JOIN dbo.DropDown ON dbo.DropDown.ID = dbo.DropDownSelection.DropDownID
)
SELECT E_ID, E_Type,
P_ID, P_Name, P_DataType, P_Required, P_OnlyOne,
PV_ID, PV_Value, PV_EntityID, PV_ValueEntityID,
PV_UnitValueID, PV_UnitID, PV_UnitName, PV_UnitDesc, PV_MeasureID, PV_MeasureName, PV_UnitValue,
PV_SelectionID, PV_DropDownID, PV_DropDownName, PV_DropDownOptionID, PV_DropDownOptionName, PV_DropDownOptionDesc,
RecursiveLevel
FROM Entities
INNER JOIN [dbo].[Entity] AS dE
ON dE.ID = PV_EntityID
The problem is the second query, the "recursive one" is getting the data I expect since I can't do the LEFT JOINs like in the first query. (At least to my understanding).
If I remove the fetching of the data that requires the LEFT (Outer) JOINs then the recursion works perfectly. My problem is I need both. Is there a way I can accomplish this?
Per http://msdn.microsoft.com/en-us/library/ms175972.aspx you can not have a left/right/outer join in a recursive CTE.
For a recursive CTE you can't use a subquery either so I sugest following this example.
They use two CTE's. The first is not recursive and does the left join to get the data it needs. The second CTE is recursive and inner joins on the first CTE. Since CTE1 is not recursive it can left join and supply default values for the missing rows and is guarenteed to work in the inner join.
However, you can also duplicate a left join with a union and subselect though it isn't really useful normally but it is interesting.
In that case, you would keep your first statement how it is. It will match all rows that join successfully.
Then UNION that query with another query that removes the join, but has a
NOT EXISTS(SELECT 1 FROM MISSING_ROWS_TABLE WHERE MAIN_TABLE.JOIN_CONDITION = MISSING_ROWS_TABLE.JOIN_CONDITION)
This gets all the rows that failed the previous join condition in query 1. You can replace the colmuns you would get from MISSING_ROWS_TABLE with NULL. I had to do this once using a coding framework that didn't support outer joins. Since recursive CTE's don't allow subqueries you have to use the first solution.