How to Join two select statements - sql

I have four tables. I wrote 2 queries independently and those are working. But what I want to do is join those two queries and generate one result.
Here is my code
Query #1
SELECT
pm.DATE
,pm.customer
,pm.gp_no AS Gatepass_Num
,pf.style
,pf.color
,pf.batch_no
,COUNT(pf.roll_no) AS Roll_QTY
,SUM(pf.meter) AS QTY
FROM
(packinglists_fabrics_items pf
,packinglists_main pm
WHERE
pf.p_id = pm.id
[AND pm.date between {DateR,RANGE1} and {DateR,RANGE2}]
[AND pm.customer_id = "{factory,false}"]
GROUP BY
pm.DATE, pm.gp_no, pf.style, pf.color, pf.batch_no)
Query #2:
SELECT
lo.DATE
,lo.customer_name
,flo.style
,flo.color
,flo.batch_no
,COUNT(flo.rowno) AS Roll_QTY
,SUM(flo.meter) AS QTY_Meter
FROM
loadinglists_fabrics_items flo, loadinglists lo
WHERE
flo.p_id = lo.id
[AND lo.date between {DateR,RANGE1} and {DateR,RANGE2}]
[AND lo.customer_id = "{factory,false}"]
GROUP BY
lo.DATE, flo.style, flo.color, flo.batch_no
batch_no is unique for loadinglists_fabrics_items table and packinglists_fabrics_items table
Result of query 1
Result of query 2
Expected output

Try like this, I assume that you are using SQL Server
SELECT A.*
,B.*
FROM (
SELECT pm.DATE
,pm.customer
,pm.gp_no AS Gatepass_Num
,pf.style
,pf.color
,pf.batch_no
,COUNT(pf.roll_no) AS Roll_QTY
,SUM(pf.meter) AS QTY
FROM packinglists_fabrics_items pf
,packinglists_main pm
WHERE pf.p_id = pm.id
AND pm.DATE BETWEEN {DateR
,RANGE1}
AND {DateR
,RANGE2}
AND pm.customer_id = "{factory,false}"
GROUP BY pm.DATE
,pm.gp_no
,pf.style
,pf.color
,pf.batch_no
) A
INNER JOIN (
SELECT lo.DATE
,lo.customer_name
,flo.style
,flo.color
,flo.batch_no
,COUNT(flo.rowno) AS Roll_QTY
,SUM(flo.meter) AS QTY_Meter
FROM loadinglists_fabrics_items flo
,loadinglists lo
WHERE flo.p_id = lo.id
AND lo.DATE BETWEEN {DateR
,RANGE1}
AND {DateR
,RANGE2}
AND lo.customer_id = "{factory,false}"
GROUP BY lo.DATE
,flo.style
,flo.color
,flo.batch_no
) B ON A.batch_no = B.batch_no

Related

How to use alias of a subquery to get the running total?

I have a UNION of 3 tables for calculating some balance and I need to get the running SUM of that balance but I can't use PARTITION OVER, because I must do it with a sql query that can work in Access.
My problem is that I cannot use JOIN on an alias subquery, it won't work.
How can I use alias in a JOIN to get the running total?
Or any other way to get the SUM that is not with PARTITION OVER, because it does not exist in Access.
This is my code so far:
SELECT korisnik_id, imePrezime, datum, Dug, Pot, (Dug - Pot) AS Balance
FROM (
SELECT korisnik_id, k.imePrezime, r.datum, SUM(IIF(u.jedinstven = 1, r.cena, k.kvadratura * r.cena)) AS Dug, '0' AS Pot
FROM Racun r
INNER JOIN Usluge u ON r.usluga_id = u.ID
INNER JOIN Korisnik k ON r.korisnik_id = k.ID
WHERE korisnik_id = 1
AND r.zgrada_id = 1
AND r.mesec = 1
AND r.godina = 2017
GROUP BY korisnik_id, k.imePrezime, r.datum
UNION ALL
SELECT korisnik_id, k.imePrezime, rp.datum, SUM(IIF(u.jedinstven = 1, rp.cena, k.kvadratura * rp.cena)) AS Dug, '0' AS Pot
FROM RacunP rp
INNER JOIN Usluge u ON rp.usluga_id = u.ID
INNER JOIN Korisnik k ON rp.korisnik_id = k.ID
WHERE korisnik_id = 1
AND rp.zgrada_id = 1
AND rp.mesec = 1
AND rp.godina = 2017
GROUP BY korisnik_id, k.imePrezime, rp.datum
UNION ALL
SELECT uu.korisnik_id, k.imePrezime, uu.datum, '0' AS Dug, SUM(uu.iznos) AS Pot
FROM UnosUplata uu
INNER JOIN Korisnik k ON uu.korisnik_id = k.ID
WHERE korisnik_id = 1
GROUP BY uu.korisnik_id, k.imePrezime, uu.datum
) AS a
ORDER BY korisnik_id
You can save a query (let's name it Query1) for the UNION of the 3 tables and then create another query that returns each row in the first query and calculates the sum of the rows that are before it (optionally checking that they are in the same group).
It should be something like this:
SELECT *, (
SELECT SUM(Value) FROM Query1 AS b
WHERE b.GroupNumber=a.GroupNumber
AND b.Position<=a.Position
) AS RunningSum
FROM Query1 AS a
However, it's more efficient to do that in the report.

Removing duplicates rows in left Joining query

SELECT Rec.[Reg_ID]
,Rec.[Reg_No]
,Rec.[Case_ID]
,Det.Deleted AS CaseDeleted
,[Status].[Status]
,Det.[Unit_Submission_Date] AS [Signature]
,TD.TargetDate AS [Target]
,TD.TargetID
FROM [dbo].[Regestrations] Rec
LEFT JOIN [dbo].[Reg_Details] Det ON Rec.Case_ID = Det.CaseID
LEFT JOIN [dbo].[lkpStatus] [Status] ON Rec.Status_ID = [Status].StatusID
LEFT JOIN TargetDate TD ON TD.RecommId = Rec.Reg_ID
WHERE (Det.MissionID = 50 AND [Status].[Status] = 1 AND Rec.Deleted = 0 AND Det.Deleted = 0)
GROUP BY Rec.[Reg_ID],Rec.[Reg_No],Rec.[Case_ID]
,[Status].[Status]
,Det.[Unit_Submission_Date]
,TD.TargetDate
,Det.Deleted
,TD.TargetID
ORDER BY TD.TargetID desc
I have the above query that is supposed to return rows with unique Rec.[Reg_No]. But joined table TargetDate can have duplicate Rec.[Reg_ID] and if thats the case i get duplicate Rec.[Reg_No] rows in my results.
Table TargetDate has a date time column so i want to eliminate the duplicate Rec.[Reg_No] by selecting 1 row with the latest date value from table TargetDate.
How do modify my Join condition or the query where clause to achive the above?
One way is to use a window function such as ROW_NUMBER() that will generate sequential number based on the specified partition. This generated number can then be used to get the latest row.
SELECT Reg_ID, Reg_No, Case_ID, CaseDeleted, [Status], Signature, [Target], TargetID
FROM
(
SELECT Rec.[Reg_ID]
,Rec.[Reg_No]
,Rec.[Case_ID]
,Det.Deleted AS CaseDeleted
,[Status].[Status]
,Det.[Unit_Submission_Date] AS [Signature]
,TD.TargetDate AS [Target]
,TD.TargetID
,RN = ROW_NUMBER() OVER (PARTITION BY Rec.[Reg_No] ORDER BY TD.TargetID DESC)
FROM [BOI].[dbo].[Regestrations] Rec
LEFT JOIN [dbo].[Reg_Details] Det ON Rec.Case_ID = Det.CaseID
LEFT JOIN [dbo].[lkpStatus] [Status] ON Rec.Status_ID = [Status].StatusID
LEFT JOIN TargetDate TD ON TD.RecommId = Rec.Reg_ID
WHERE (Det.MissionID = 50 AND [Status].[Status] = 1 AND Rec.Deleted = 0 AND Det.Deleted = 0)
) subQuery
WHERE RN = 1
ORDER BY TargetID desc
This query can work correctly if you remove TD.TargetDate from GROUP BY clause and compute what you really need in output - MAX(TD.TargetDate)
But preferable way it to avoid GROUP BY clause at all:
...
FROM [BOI].[dbo].[Regestrations] Rec
LEFT JOIN [dbo].[Reg_Details] Det ON Rec.Case_ID = Det.CaseID
LEFT JOIN [dbo].[lkpStatus] [Status] ON Rec.Status_ID = [Status].StatusID
OUTER APPLY(
SELECT TOP 1 td.TargetDate, td.TargetID
FROM TargetDate TD
WHERE TD.RecommId = Rec.Reg_ID
ORDER BY TD.TargetDate DESC
) td
...
You should first find latest TargetDate for each Reg_ID or RecommId. Then you can use your normal join with TargetDate table just this time with matching both the RecommId and TargetDate.
Try this Query:
SELECT Rec.[Reg_ID]
,Rec.[Reg_No]
,Rec.[Case_ID]
,Det.Deleted AS CaseDeleted
,[Status].[Status]
,Det.[Unit_Submission_Date] AS [Signature]
,TD.TargetDate AS [Target]
,TD.TargetID
FROM [BOI].[dbo].[Regestrations] Rec
LEFT JOIN [dbo].[Reg_Details] Det ON Rec.Case_ID = Det.CaseID
LEFT JOIN [dbo].[lkpStatus] [Status] ON Rec.Status_ID = [Status].StatusID
LEFT JOIN (SELECT RecommId, MAX(TargetDate) MaxTargetDate GROUP BY RecommId) TDWithLatestDate ON TDWithLatestDate.RecommId = Rec.Reg_ID
LEFT OUTER JOIN TargetDate ON TD.RecommId = TDWithLatestDate.RecommId AND TD.TargetDate = TDWithLatestDate.MaxTargetDate
WHERE (Det.MissionID = 50
AND [Status].[Status] = 1
AND Rec.Deleted = 0
AND Det.Deleted = 0
)
GROUP BY Rec.[Reg_ID]
,Rec.[Reg_No]
,Rec.[Case_ID]
,[Status].[Status]
,Det.[Unit_Submission_Date]
,TD.TargetDate
,Det.Deleted
,TD.TargetID
ORDER BY TD.TargetID desc
You can improve this query if you want to avoid tie when there more than one record fighting to be latest.

Sum a union query

I'm using Microsoft SQL Svr Mgmt Studio 2008. I don't have access to create a temporary table (company restricts ability to create or modify tables) or I would use that to solve this problem.
I have successfully used a union query to combine the results of three select queries. Now I am trying to sum the results of the union.
When I execute the query below I receive:
Incorrect syntax near the keyword 'GROUP'
And then when I remove the group by I get:
Incorrect syntax near ')'
Here's my query so far:
Select Period, PCC, SUM(BasicHits), SUM(FareHits), SUM(SearchHits)
From (
SELECT AAAPeriod AS Period,
AAAFromPCC AS PCC,
- SUM(AAABasic) AS BasicHits,
- SUM(AAAFare) AS FareHits,
- SUM(AAASearch) AS SearchHits
FROM HitsAaa
HAVING (AAAPeriod = N'2010-10')
UNION ALL
SELECT AAAPeriod,
AAAtoPCC,
SUM(AAABasic),
SUM(AAAFare),
SUM(AAASearch)
FROM HitsAaa
HAVING (AAAPeriod = N'2010-10')
UNION ALL
SELECT AgtPeriod,
AgtPcc,
SUM(AgtBasic),
SUM(AgtFare),
SUM(AgtSearch)
FROM HitsAgent
HAVING (AgtPeriod = N'2010-10')
)GROUP BY Period, PCC
I haven't been able to find a solution to this on any of the previous questions.
You need to alias your derived table, you must also use a group by with a having clause.
SELECT
q1.Period,
q1.PCC,
SUM(q1.BasicHits),
SUM(q1.FareHits),
SUM(q1.SearchHits)
FROM (SELECT
AAAPeriod AS Period,
AAAFromPCC AS PCC,
- SUM(AAABasic) AS BasicHits,
- SUM(AAAFare) AS FareHits,
- SUM(AAASearch) AS SearchHits
FROM HitsAaa
GROUP BY
AAAPeriod,
AAAFromPCC
HAVING (AAAPeriod = N'2010-10')
UNION ALL
SELECT
AAAPeriod AS Period,
AAAtoPCC AS PCC,
SUM(AAABasic) AS BasicHits,
SUM(AAAFare) AS FareHits,
SUM(AAASearch) AS SearchHits
FROM HitsAaa
GROUP BY
AAAPeriod,
AAAtoPCC
HAVING (AAAPeriod = N'2010-10')
UNION ALL
SELECT
AgtPeriod AS Period,
AgtPcc AS PCC,
SUM(AgtBasic) AS BasicHits,
SUM(AgtFare) AS FareHits,
SUM(AgtSearch) AS SearchHits
FROM HitsAgent
GROUP BY
AgtPeriod,
AgtPCC
HAVING (AgtPeriod = N'2010-10')) q1
GROUP BY
q1.Period,
q1.PCC
SQL Server requires that you define a table alias for a derived table/inline view:
SELECT x.period, x.pcc, SUM(x.BasicHits), SUM(x.FareHits), SUM(x.SearchHits)
FROM (SELECT AAAPeriod AS Period,
AAAFromPCC AS PCC,
- SUM(AAABasic) AS BasicHits,
- SUM(AAAFare) AS FareHits,
- SUM(AAASearch) AS SearchHits
FROM HitsAaa
WHERE AAAPeriod = N'2010-10'
GROUP BY aaaperiod, aaafrompcc
UNION ALL
SELECT AAAPeriod,
AAAtoPCC,
SUM(AAABasic),
SUM(AAAFare),
SUM(AAASearch)
FROM HitsAaa
WHERE AAAPeriod = N'2010-10'
GROUP BY aaaperiod, aaafrompcc
UNION ALL
SELECT AgtPeriod,
AgtPcc,
SUM(AgtBasic),
SUM(AgtFare),
SUM(AgtSearch)
FROM HitsAgent
WHERE AgtPeriod = N'2010-10'
GROUP BY agtperiod, agtpcc) AS x
GROUP BY x.period, x.pcc
I don't have access to create a
temporary table (company restricts
ability to create or modify tables) or
I would use that to solve this
problem.
Instead of a temporary table, try using a table variable:
declare #t table (id int primary key, col1 varchar(50))
insert #t (col1) values ('hello table variable')
select * from #t
A table variable can do most of the things a temporary table can.
Like Martin's (now deleted) answer suggests, consider giving the subquery an alias, like:
select ... list of columns ...
from (
... subquery ...
) as SubQueryAlias
group by
col1
And in your subquery, the having should probably be a where:
...
FROM HitsAaa
WHERE (AAAPeriod = N'2010-10')
...
Change your first line to
Select T.Period, T.PCC, SUM(T.BasicHits), SUM(T.FareHits), SUM(T.SearchHits)
and the last line to
) T GROUP BY T.Period, T.PCC
You need to define a table alias (in this case T) for inner tables
Also, you need to GROUP BY the inner queries
select R."Artigo", R."Dscription" as "Descricao",
R."Codigo", R."Cliente",
R."ItmsGrpCod", Sum(R."Qtd/Kg") as "Qtd/Kg", Sum(R."Valor") as "Valor",
Sum(R."Valor")/Sum(R."Qtd/Kg") as "PMVL"
from (
select T1."ItemCode" as "Artigo", T1."Dscription",
T0."CardCode" as "Codigo", T0."CardName" as "Cliente",
T3."ItmsGrpCod", Sum(T1."Quantity")-1 as "Qtd/Kg",
Sum(T1."LineTotal")-1 as "Valor",
( Sum(T1."LineTotal") / Sum(T1."Quantity") ) as "PMVL"
from
ORIN T0 INNER JOIN RIN1 T1 ON T0."DocEntry" = T1."DocEntry"
RIGHT JOIN OITM T3 ON T1."ItemCode" = T3."ItemCode"
LEFT JOIN IBT1 T2 ON T0."DocEntry" = T2."BaseEntry" AND T1."ItemCode"=T2."ItemCode" and T2."BaseLinNum"=T1."LineNum"
where T0."DocDate" >= ('2021-03-19') and T0."DocDate" <= ('2021-03-19')
and T3."ItmsGrpCod" like '___'
and T0.CANCELED = 'N'
group by T1."ItemCode", T1."Dscription", T0."CardCode", T0."CardName", T3."ItmsGrpCod"
union
-- facturas
select T1."ItemCode" as "Artigo", T1."Dscription",
T0."CardCode" as "Codigo", T0."CardName" as "Cliente",
T3."ItmsGrpCod", Sum(T1."Quantity") as "Qtd/Kg", Sum(T1."LineTotal") as "Valor", ( Sum(T1."LineTotal") / Sum(T1."Quantity") ) as "PMVL"
from
OINV T0 INNER JOIN INV1 T1 ON T0."DocEntry" = T1."DocEntry"
-- LEFT JOIN OITM T3 ON T1."ItemCode" = T3."CardCode"
left JOIN OITM T3 ON T1."ItemCode" = T3."ItemCode"
-- INNER JOIN OITM T3 ON T3."ItemCode" = T3."CardCode"
LEFT JOIN IBT1 T2 ON T0."DocEntry" = T2."BaseEntry" AND T1."ItemCode"=T2."ItemCode" and T2."BaseLinNum"=t1."LineNum"
where T0."DocDate" >= ('2021-03-19') and T0."DocDate" <= ('2021-03-19')
and T3."ItmsGrpCod" like '___'
group by T1."ItemCode", T1."Dscription", T0."CardCode", T0."CardName",T3."ItmsGrpCod"
) as R
group by R."Artigo", R."Dscription", R."Codigo", R."Cliente",R."ItmsGrpCod"

SQL Union Query

SELECT pv.PropertyID, COUNT(pv.VisitID) AS InitialVisit
FROM tblPAppointments pa INNER JOIN tblPropertyVisit pv ON pv.AppID = pa.AppID
WHERE pv.Status = 0
GROUP BY pv.PropertyID
UNION ALL
SELECT jv.PropertyID, COUNT(jv.JobVistID) AS JobVisit
FROM tblPAppointments pa INNER JOIN tblJobVisits jv ON jv.AppID = pa.AppID
WHERE jv.VisitStatus = 1
GROUP BY jv.PropertyID
I need to get InitialVisit count and JobVisit count in two separate columns.above query returns just two columns (PropertyID,InitialVisit).
Use a NULL as a placeholder for the column that there won't be any output for:
SELECT pv.PropertyID,
COUNT(pv.VisitID) AS InitialVisit,
NULL AS jobvisit
FROM tblPAppointments pa
JOIN tblPropertyVisit pv ON pv.AppID = pa.AppID
WHERE pv.Status = 0
GROUP BY pv.PropertyID
UNION ALL
SELECT jv.PropertyID,
NULL AS initialvisit,
COUNT(jv.JobVistID) AS JobVisit
FROM tblPAppointments pa
JOIN tblJobVisits jv ON jv.AppID = pa.AppID
WHERE jv.VisitStatus = 1
GROUP BY jv.PropertyID
This will return three columns. The column alias is necessary in the first query, but not in the second -- I aliased both to make it clear what is happening.
Be aware that using NULL like this in SQL Server will require you to use CAST/CONVERT on the NULL for data types other than INT because SQL Server defaults the NULL to an INT data type (as odd as that is).
An alternate query that doesn't use UNION:
SELECT x.propertyid,
COUNT(y.visitid) AS initialvisit,
COUNT(z.jobvisitid) AS jobvisit
FROM (SELECT pv.propertyid
FROM TBLPROPERTYVISIT pv
WHERE EXISTS (SELECT NULL
FROM TBLAPPOINTMENTS a
WHERE a.appid = pv.appid)
UNION
SELECT jv.propertyid
FROM TBLJOBVISIT jv
WHERE EXISTS (SELECT NULL
FROM TBLAPPOINTMENTS a
WHERE a.appid = jv.appid)) x
LEFT JOIN TBLPROPERTYVISIT y ON y.propertyid = x.propertyid
LEFT JOIN TBLJOBVISIT z ON z.propertyid = x.propertyid
GROUP BY x.propertyid
No need for a UNION at all. And you don't use tblPAppointments either
Edited to allow for no rows in one of the tables. Still one row output though
SELECT
ISNULL(pv2.PropertyID, jv2.PropertyID),
ISNULL(pv2.InitialVisit, 0),
ISNULL(jv2.JobVisit, 0)
FROM
(
SELECT pv.PropertyID, COUNT(pv.VisitID) AS InitialVisit
FROM tblPropertyVisit pv
WHERE pv.Status = 0
GROUP BY pv.PropertyID
) pv2
FULL OUTER JOIN
(
SELECT jv.PropertyID, COUNT(jv.JobVistID) AS JobVisit
FROM tblJobVisits jv
WHERE jv.VisitStatus = 1
GROUP BY jv.PropertyID
) jv2 ON pv2.PropertyID = jv2.PropertyID

Need to speed up the results of this SQL statement. Any advice?

I've got the following SQL Statement that needs some major speed up. The problem is I need to search on two fields, where each of them is calling several sub-selects. Is there a way to join the two fields together so I call the sub-selects only once?
SELECT billyr, billno, propacct, vinid, taxpaid, duedate, datepif, propdesc
FROM trcdba.billspaid
WHERE date(datepif) > '01/06/2009'
AND date(datepif) <= '01/06/2010'
AND custno in
(select custno from cwdba.txpytaxid where taxpayerno in
(select taxpayerno from cwdba.txpyaccts where accountno in
(select accountno from rtadba.reasacct where controlno = 1234567)))
OR custno2 in
(select custno from cwdba.txpytaxid where taxpayerno in
(select taxpayerno from cwdba.txpyaccts where accountno in
(select accountno from rtadba.reasacct where controlno = 1234567)))
I would use joins instead of the embedded sub-queries.
when you use a function on the column:
date(datepif) > '01/06/2009'
AND date(datepif) <= '01/06/2010'
an index will NOT be used. Try something like this
datepif > someconversionhere('01/06/2009')
AND datepif <= someconversionhere('01/06/2010')
Use inner joins too. There isn't any info in the question to indicate table size or if there is an index or not, so this is a guess and should work best if there are many more rows in billspaid for the date range vs rows that match the joining tables for r.controlno = 1234567, which I suspect is the case:
SELECT
COALESCE(b1.billyr,b2.billyr) AS billyr
,COALESCE(b1.billno,b2.billno) AS billno
,COALESCE(b1.propacct,b2.propacct) AS propacct
,COALESCE(b1.vinid,b2.vinid) AS vinid
,COALESCE(b1.taxpaid,b2.taxpaid) AS taxpaid
,COALESCE(b1.duedate,b2.duedate) AS duedate
,COALESCE(b1.datepif,b2.datepif) AS datepif
,COALESCE(b1.propdesc,b2.propdesc) AS propdesc
FROM rtadba.reasacct r
INNER JOIN cwdba.txpyaccts a ON r.accountno=t.accountno
INNER JOIN cwdba.txpytaxid t ON a.taxpayerno=t.taxpayerno
LEFT OUTER JOIN trcdba.billspaid b1 ON t.custno=b1.custno AND b1.datepif > someconversionhere('01/06/2009') AND b1.datepif <= someconversionhere('01/06/2010')
LEFT OUTER JOIN trcdba.billspaid b2 ON t.custno2=b2.custno AND b2.datepif > someconversionhere('01/06/2009') AND b2.datepif <= someconversionhere('01/06/2010')
WHERE r.controlno = 1234567
AND COALESCE(b1.custno,b2.custno) IS NOT NULL
create an index for each of these:
rtadba.reasacct.controlno and cover on accountno
cwdba.txpyaccts.accountno and cover on taxpayerno
cwdba.txpytaxid.taxpayerno and cover on custno
trcdba.billspaid.custno +datepif
trcdba.billspaid.custno2 +datepif
Here's the same thing using JOIN instead of sub queries.
SELECT billyr, billno, propacct, vinid, taxpaid, duedate, datepif, propdesc
FROM billspaid
INNER JOIN txpytaxid
ON txpytaxid.custno = billspaid.custno OR txpytaxid.custno = billspaid.custno2
INNER JOIN txpyaccts
ON txpyaccts.taxpayerno = txpytaxid.taxpayerno
INNER JOIN reasacct
ON reasacct.accountno = txpyaccts.accountno AND reasacct.controlno = 1234567
WHERE date(datepif) > '01/06/2009'
AND date(datepif) <= '01/06/2010'
However, if the OR in the JOIN is giving you performance problems, you can always try using a union:
(SELECT billyr, billno, propacct, vinid, taxpaid, duedate, datepif, propdesc
FROM billspaid
INNER JOIN txpytaxid
ON txpytaxid.custno = billspaid.custno
INNER JOIN txpyaccts
ON txpyaccts.taxpayerno = txpytaxid.taxpayerno
INNER JOIN reasacct
ON reasacct.accountno = txpyaccts.accountno AND reasacct.controlno = 1234567
WHERE date(datepif) > '01/06/2009'
AND date(datepif) <= '01/06/2010')
UNION
(SELECT billyr, billno, propacct, vinid, taxpaid, duedate, datepif, propdesc
FROM billspaid
INNER JOIN txpytaxid
ON txpytaxid.custno = billspaid.custno2
INNER JOIN txpyaccts
ON txpyaccts.taxpayerno = txpytaxid.taxpayerno
INNER JOIN reasacct
ON reasacct.accountno = txpyaccts.accountno AND reasacct.controlno = 1234567
WHERE date(datepif) > '01/06/2009'
AND date(datepif) <= '01/06/2010')
Use EXISTS instead of IN ( unless the result set of the IN subquery is very small).
If you do UNION instead of OR ( which should be functionally equivalent ) use UNION ALL instead.