SQL Statement Help Needed:Query within a Query - sql

I am working on a query where I need to compile a list of of members who have a particular group of products associated with their, from a particular site and then for each member in that list retrieve all of the products on their account.
The first piece of the query is this:
SELECT
MEMBERS.memid
FROM
SITES
INNER JOIN
MEMBERS ON SITES.siteid = MEMBERS.siteid
INNER JOIN
SS ON MEMBERS.memid = SS.memid
INNER JOIN
PRODUCTCATS
INNER JOIN
PRODUCTS ON PRODUCTCATS.productcatid = PRODUCTS.productcatid
ON SS.productid = PRODUCTS.productid
INNER JOIN
EMPLOYEES ON SS.employeeid = EMPLOYEES.employeeid
WHERE
(PRODUCTS.productcatid = 77)
AND (SS.initialdate BETWEEN #rvPurchaseStart AND #rvPurchaseEnd)
From that list, I then need the following query to run for each member in that list:
SELECT
SITES.sitename, MEMBERS.scancode, MEMBERS.lname,
MEMBERS.fname, MEMBERS.mtypeid, MEMBERS.status,
PRODUCTS.description, SS.initialdate,
SS.initialquantity, SS.usedquantity, SS.dateexpire,
EMPLOYEES.lname AS Expr1, EMPLOYEES.fname AS Expr2
FROM
SITES
INNER JOIN
MEMBERS ON SITES.siteid = MEMBERS.siteid
INNER JOIN
SS ON MEMBERS.memid = SS.memid
INNER JOIN
PRODUCTCATS
INNER JOIN
PRODUCTS ON PRODUCTCATS.productcatid = PRODUCTS.productcatid
ON SS.productid = PRODUCTS.productid
INNER JOIN
EMPLOYEES ON SS.employeeid = EMPLOYEES.employeeid
WHERE
(PRODUCTS.productcatid <> '68')
AND (PRODUCTS.departmentid = '5')
AND (MEMBERS.status = 'A')
AND (SS.usedquantity < SS.initialquantity)
AND (PRODUCTS.scancode <> 'PASSCOMP1' OR
PRODUCTS.scancode <> 'PASSCOMP3' OR
PRODUCTS.scancode <> 'PASSCOMP5')
AND (PRODUCTS.inactive = 'False')
I really appreciate the help!!!

Sometnihg like this? Just add the fist query as table to your second query.
SELECT
SITES.sitename, MEMBERS.scancode,
MEMBERS.lname, MEMBERS.fname, MEMBERS.mtypeid,
MEMBERS.status, PRODUCTS.description, SS.initialdate,
SS.initialquantity, SS.usedquantity, SS.dateexpire,
EMPLOYEES.lname AS Expr1, EMPLOYEES.fname AS Expr2
FROM
SITES
INNER JOIN
MEMBERS ON SITES.siteid = MEMBERS.siteid
INNER JOIN
SS ON MEMBERS.memid = SS.memid
INNER JOIN
PRODUCTCATS
INNER JOIN
PRODUCTS ON PRODUCTCATS.productcatid = PRODUCTS.productcatid
ON SS.productid = PRODUCTS.productid
INNER JOIN
EMPLOYEES ON SS.employeeid = EMPLOYEES.employeeid
INNER JOIN
(SELECT
MEMBERS.memid
FROM
SITES
INNER JOIN
MEMBERS ON SITES.siteid = MEMBERS.siteid
INNER JOIN
SS ON MEMBERS.memid = SS.memid
INNER JOIN
PRODUCTCATS
INNER JOIN
PRODUCTS ON PRODUCTCATS.productcatid = PRODUCTS.productcatid
ON SS.productid = PRODUCTS.productid
INNER JOIN
EMPLOYEES ON SS.employeeid = EMPLOYEES.employeeid
WHERE
(PRODUCTS.productcatid = 77)
AND (SS.initialdate BETWEEN #rvPurchaseStart AND #rvPurchaseEnd)) TMP_TABLE ON MEMBERS.memid = TMP_TABLE.memid
WHERE
(PRODUCTS.productcatid <> '68')
AND (PRODUCTS.departmentid = '5')
AND (MEMBERS.status = 'A')
AND (SS.usedquantity < SS.initialquantity)
AND (PRODUCTS.scancode <> 'PASSCOMP1' OR PRODUCTS.scancode <> 'PASSCOMP3' OR PRODUCTS.scancode <> 'PASSCOMP5')
AND (PRODUCTS.inactive = 'False')

Related

SQL Nesting Logic Needed

I have a situation where I need to build a query that pulls gives me a list of member that used an item on their account in timeframe one but that did not use on item on their account in timeframe two.
SELECT DISTINCT SS.memid
FROM SS
INNER JOIN SSUSED ON SS.ssid = SSUSED.ssid
INNER JOIN MEMBERS AS MEMBERS_1 ON SS.memid = MEMBERS_1.memid
INNER JOIN PRODUCTS ON SS.productid = PRODUCTS.productid
INNER JOIN PRODUCTCATS ON PRODUCTS.productcatid = PRODUCTCATS.productcatid
INNER JOIN EMPLOYEES ON SSUSED.employeeid = EMPLOYEES.employeeid
AND NOT EXISTS
(
SELECT DISTINCT SS_1.memid
FROM SS AS SS_1
INNER JOIN SSUSED AS SSUSED_1 ON SS_1.ssid = SSUSED_1.ssid
INNER JOIN MEMBERS AS MEMBERS_1 ON SS_1.memid = MEMBERS_1.memid
INNER JOIN PRODUCTS AS PRODUCTS_1 ON SS_1.productid = PRODUCTS_1.productid
INNER JOIN PRODUCTCATS AS PRODUCTCATS_1 ON PRODUCTS_1.productcatid = PRODUCTCATS_1.productcatid
INNER JOIN EMPLOYEES AS EMPLOYEES_1 ON SSUSED_1.employeeid = EMPLOYEES_1.employeeid
WHERE
MEMBERS_1.siteid = #rvSite
AND SSUSED_1.usedate BETWEEN #rvStartWeek2
AND #rvEndWeek2
AND PRODUCTS_1.productcatid IN (27,28,29,58,77,75,30,61,31,32,47,68)
)
WHERE MEMBERS_1.siteid = #rvSite
AND SSUSED.usedate BETWEEN #rvStartWeek1
AND #rvEndWeek1
AND PRODUCTS.productcatid IN (27,28,29,58,77,75,30,61,31,32,47,68)
The issue that I am running into is that when I try the query this way I get the following error:

Issues With Excluding Results From Subquery

I am attempting to retrieve a list of members (MEMBERS table) who have purchased (ARTRANS table) a product from one of three product categories (PRODUCTCATS table) during a specified period (a month) and then have not purchased a product from that category in the following period (month).
Both queries work by themselves but when I put them together I do not pull any results. PLEASE HELP!
SELECT MEMBERS.lname
, MEMBERS.fname
, MEMBERS.email
, PRODUCTS.scancode
, PRODUCTS.description
, ARTRANS.datetrans
, ARTRANS.memid
, ARTRANS.invoice
, ARTRANSITEMS.price
, ARTRANSITEMS.quantity
FROM PRODUCTS
INNER JOIN ARTRANSITEMS
ON PRODUCTS.productid = ARTRANSITEMS.productid
INNER JOIN ARTRANS
ON ARTRANSITEMS.transid = ARTRANS.transid
INNER JOIN PRODUCTCATS
ON PRODUCTS.productcatid = PRODUCTCATS.productcatid
INNER JOIN MEMBERS
ON ARTRANS.memid = MEMBERS.memid
AND NOT EXISTS (
SELECT M2.memid
FROM PRODUCTS AS P2
INNER JOIN ARTRANSITEMS AS ATI
ON P2.productid = ATI.productid
INNER JOIN ARTRANS AS ART2
ON ATI.transid = ART2.transid
INNER JOIN PRODUCTCATS AS PC2
ON P2.productcatid = PC2.productcatid
INNER JOIN MEMBERS AS M2
ON ART2.memid = M2.memid
WHERE (
P2.productcatid = '20'
OR P2.productcatid = '21'
OR P2.productcatid = '78'
)
AND (ART2.datetrans BETWEEN DATEADD(month, 1, #rvMonthOneStart) AND DATEADD(month, 1, #rvMonthOneEnd))
)
WHERE (
PRODUCTS.productcatid = '20'
OR PRODUCTS.productcatid = '21'
OR PRODUCTS.productcatid = '78'
)
AND (ARTRANS.datetrans BETWEEN #rvMonthOneStart AND #rvMonthOneEnd)
Try this....
SELECT MEMBERS.lname, MEMBERS.fname, MEMBERS.email, PRODUCTS.scancode
, PRODUCTS.description, ARTRANS.datetrans, ARTRANS.memid
, ARTRANS.invoice, ARTRANSITEMS.price, ARTRANSITEMS.quantity
FROM PRODUCTS
INNER JOIN ARTRANSITEMS ON PRODUCTS.productid = ARTRANSITEMS.productid
INNER JOIN ARTRANS ON ARTRANSITEMS.transid = ARTRANS.transid
INNER JOIN PRODUCTCATS ON PRODUCTS.productcatid = PRODUCTCATS.productcatid
INNER JOIN MEMBERS ON ARTRANS.memid = MEMBERS.memid
WHERE PRODUCTS.productcatid IN ('20' ,'21','78')
AND (ARTRANS.datetrans BETWEEN #rvMonthOneStart AND #rvMonthOneEnd)
AND NOT EXISTS (SELECT 1
FROM PRODUCTS AS P2
INNER JOIN ARTRANSITEMS AS ATI ON P2.productid = ATI.productid
INNER JOIN ARTRANS AS ART2 ON ATI.transid = ART2.transid
INNER JOIN PRODUCTCATS AS PC2 ON P2.productcatid = PC2.productcatid
INNER JOIN MEMBERS AS M2 ON ART2.memid = M2.memid
WHERE PRODUCTS.productcatid IN ('20' ,'21','78')
AND (ART2.datetrans BETWEEN DATEADD(month, 1, #rvMonthOneStart) AND DATEADD(month, 1, #rvMonthOneEnd))
AND M2.memid = MEMBERS.memid)

SQL Logic for Multi-Matches

I have a situation where I am pulling back data from several tables MEMBERS, SS, and SSUSED. Where 'MEMBERS' is the table with member data, 'SS' is the table with the products that a member has purchased on their account and SSUSED is a table that stores the usage of the products. Products can have 1, 6 or 12 usages. So there can be a one to one, one to six, or one to twelve matching ratio. When I run my query, I am bringing back all of the usages. I only need to bring back the latest one (SSUSED.usedate).
I am also trying to filter out certain products and product categories and that doesn't seem to be totally working. I get a random product here and there and I can not seem to isolate the issue. I think it may be because my logic isn't written in a clean efficient manner.
CODE:
SELECT DISTINCT
MEMBERS.scancode, MEMBERS.lname, MEMBERS.fname, MEMBERS.mtypeid, MEMBERS.status, MEMBERS.lastvisit, MEMBERS.datejoin,
PRODUCTS.description, EMPLOYEES.lname AS EmpLname, EMPLOYEES.fname AS EmpFName, SSUSED.transactiontype, SS.initialdate, SS.initialquantity,
SS.usedquantity, MEMBERTYPES.mtype, SS.ssid, SSUSED.usedate
FROM PRODUCTCATS INNER JOIN
PRODUCTS ON PRODUCTCATS.productcatid = PRODUCTS.productcatid INNER JOIN
SS ON PRODUCTS.productid = SS.productid INNER JOIN
MEMBERS ON SS.memid = MEMBERS.memid LEFT OUTER JOIN
SSUSED ON SS.ssid = SSUSED.ssid INNER JOIN
EMPLOYEES ON SSUSED.employeeid = EMPLOYEES.employeeid INNER JOIN
MEMBERTYPES ON MEMBERS.mtypeid = MEMBERTYPES.mtypeid
WHERE (SS.memid IN
(SELECT DISTINCT SS_1.memid
FROM SS AS SS_1 INNER JOIN
SSUSED AS SSUSED_1 ON SS_1.ssid = SSUSED_1.ssid INNER JOIN
MEMBERS AS MEMBERS_1 ON SS_1.memid = MEMBERS_1.memid
WHERE (MEMBERS_1.siteid = #rvSite) AND (SS_1.productid = '324' OR
SS_1.productid = '326') AND (SSUSED_1.usedate BETWEEN #rvStartDate AND #rvEndDate) AND (SSUSED_1.transactiontype = 'Use'))) AND
(PRODUCTS.productcatid = '27' OR
PRODUCTS.productcatid = '28' OR
PRODUCTS.productcatid = '29' OR
PRODUCTS.productcatid = '58' OR
PRODUCTS.productcatid = '77' OR
PRODUCTS.productcatid = '75' OR
PRODUCTS.productcatid = '30' OR
PRODUCTS.productcatid = '61' OR
PRODUCTS.productcatid = '31' OR
PRODUCTS.productcatid = '32' OR
PRODUCTS.productcatid = '47' OR
PRODUCTS.productcatid = '68') AND (SS.productid <> '32' OR
SS.productid <> '335' OR
SS.productid <> '350' OR
SS.productid <> '618' OR
SS.productid <> '1312' OR
SS.productid <> '1646' OR
SS.productid <> '54987' OR
SS.productid <> '55937' OR
SS.productid <> '58289' OR
SS.productid <> '58876' OR
SS.productid <> '601691') AND (SSUSED.transactiontype = 'Use' OR
SSUSED.transactiontype = 'Expired') AND (SSUSED.usedate >= #rvStartDate)
This doesn't really answer the question but demonstrates how much cleaner this query can be with some formatting, aliases and converting those huge lists into IN predicates.
SELECT DISTINCT m.scancode
, m.lname
, m.fname
, m.mtypeid
, m.STATUS
, m.lastvisit
, m.datejoin
, p.description
, e.lname AS EmpLname
, e.fname AS EmpFName
, su.transactiontype
, SS.initialdate
, SS.initialquantity
, SS.usedquantity
, mt.mtype
, SS.ssid
, su.usedate
FROM PRODUCTCATS pc
INNER JOIN PRODUCTS p ON pc.productcatid = p.productcatid
INNER JOIN SS ON p.productid = SS.productid
INNER JOIN MEMBERS m ON SS.memid = m.memid
LEFT JOIN SSUSED su ON SS.ssid = su.ssid
INNER JOIN EMPLOYEES e ON su.employeeid = e.employeeid
INNER JOIN MEMBERTYPES mt ON m.mtypeid = mt.mtypeid
WHERE SS.memid IN
(
SELECT DISTINCT SS_1.memid
FROM SS AS SS_1
INNER JOIN SSUSED AS SSUSED_1 ON SS_1.ssid = SSUSED_1.ssid
INNER JOIN MEMBERS AS MEMBERS_1 ON SS_1.memid = MEMBERS_1.memid
WHERE MEMBERS_1.siteid = #rvSite
AND SS_1.productid in ('324', '326')
AND SSUSED_1.usedate BETWEEN #rvStartDate AND #rvEndDate
AND SSUSED_1.transactiontype = 'Use'
)
AND p.productcatid in('27', '28', '29', '58', '77', '75', '30', '61', '31', '32', '47', '68')
AND SS.productid in ('32', '335', '350', '618', '1312', '1646', '54987', '55937', '58289', '58876', '601691')
AND su.transactiontype in ('Use', 'Expired'
AND su.usedate >= #rvStartDate
To actually be able to help with the question we need some understanding of what this is supposed to be doing and what isn't working.

Extract between row counts

How can I make the following statement extract row 100 to row 200:
SELECT Offices.OfficeID, ContractsBooksCommodities.CommodityID
FROM ((((Offices
INNER JOIN tbl_Sales ON Offices.CompanyID = tbl_Sales.CompanyID)
INNER JOIN ContractBooks ON tbl_Sales.CompanyID = ContractBooks.CompanyID)
INNER JOIN ContractsBooksAds ON ContractBooks.ContractNum = ContractsBooksAds.ContractNum)
INNER JOIN ContractsBooksBrands ON ContractsBooksAds.ContractNum = ContractsBooksBrands.ContractNum)
INNER JOIN ContractsBooksCommodities ON ContractsBooksBrands.ContractNum = ContractsBooksCommodities.ContractNum;
This might be slow:
SELECT Top 101 Offices.OfficeID, ContractsBooksCommodities.CommodityID
FROM ((((Offices
INNER JOIN tbl_Sales ON Offices.CompanyID = tbl_Sales.CompanyID)
INNER JOIN ContractBooks ON tbl_Sales.CompanyID = ContractBooks.CompanyID)
INNER JOIN ContractsBooksAds ON ContractBooks.ContractNum = ContractsBooksAds.ContractNum)
INNER JOIN ContractsBooksBrands ON ContractsBooksAds.ContractNum = ContractsBooksBrands.ContractNum)
INNER JOIN ContractsBooksCommodities ON ContractsBooksBrands.ContractNum = ContractsBooksCommodities.ContractNum
WHERE Offices.OfficeID NOT IN (SELECT Top 99 Offices.OfficeID
FROM ((((Offices
INNER JOIN tbl_Sales ON Offices.CompanyID = tbl_Sales.CompanyID)
INNER JOIN ContractBooks ON tbl_Sales.CompanyID = ContractBooks.CompanyID)
INNER JOIN ContractsBooksAds ON ContractBooks.ContractNum = ContractsBooksAds.ContractNum)
INNER JOIN ContractsBooksBrands ON ContractsBooksAds.ContractNum = ContractsBooksBrands.ContractNum)
INNER JOIN ContractsBooksCommodities ON ContractsBooksBrands.ContractNum = ContractsBooksCommodities.ContractNum
ORDER BY Offices.OfficeID, ContractsBooksCommodities.CommodityID)
ORDER BY Offices.OfficeID, ContractsBooksCommodities.CommodityID
I do not know what fields make your sort unique, but that is what you need because MS Access will return matches otherwise.

Terrible access database issue

I have a terrible database from a client and I need to count the number of results from a query, which is as follows:
SELECT
Offices.OfficeID
, ContractsBooksCommodities.CommodityID
FROM ((((Offices
INNER JOIN tbl_Sales
ON Offices.CompanyID = tbl_Sales.CompanyID)
INNER JOIN ContractBooks
ON tbl_Sales.CompanyID = ContractBooks.CompanyID)
INNER JOIN ContractsBooksAds
ON ContractBooks.ContractNum = ContractsBooksAds.ContractNum)
INNER JOIN ContractsBooksBrands
ON ContractsBooksAds.ContractNum = ContractsBooksBrands.ContractNum)
INNER JOIN ContractsBooksCommodities
ON ContractsBooksBrands.ContractNum = ContractsBooksCommodities.ContractNum;
How can I make this count the number of records returned?
In general,
select count(*)
from (
your-select-query
)
will give you the number of records returned by your query.
COUNT and GROUP BY would be my guess:
SELECT Offices.OfficeID, ContractsBooksCommodities.CommodityID, COUNT(*) AS COUNT
FROM ((((Offices INNER JOIN tbl_Sales ON Offices.CompanyID = tbl_Sales.CompanyID) INNER JOIN ContractBooks ON tbl_Sales.CompanyID = ContractBooks.CompanyID) INNER JOIN ContractsBooksAds ON ContractBooks.ContractNum = ContractsBooksAds.ContractNum) INNER JOIN ContractsBooksBrands ON ContractsBooksAds.ContractNum = ContractsBooksBrands.ContractNum) INNER JOIN ContractsBooksCommodities ON ContractsBooksBrands.ContractNum = ContractsBooksCommodities.ContractNum
GROUP BY Offices.OfficeID, ContractsBooksCommodities.CommodityID
ORDER BY Offices.OfficeID, ContractsBooksCommodities.CommodityID