Issues With Excluding Results From Subquery - sql

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)

Related

sql - how to sum a dynamically created column with the same id?

select
Cu.CustomerNum, Cu.Name, sum(Cio1.Quantity * C1.Price) AS Total_Income
from
Orders O1
inner join
CoursesInOrder Cio1 on O1.OrderNum = Cio1.OrderNum
inner join
Customer Cu on Cu.CustomerNum = O1.CustomerNum
inner join
Course C1 on C1.CourseNum = Cio1.CourseNum
where
O1.CustomerNum in (select O.CustomerNum
from Course C
inner join CoursesInOrder Cio on C.CourseNum = Cio.CourseNum
inner join Orders O on O.OrderNum= Cio.OrderNum
where C.CourseNum = '99771'
and year(O.Shiftdate) = '2014'
group by O.CustomerNum
having count(O.CustomerNum) > 2)
[Current output]
[Wanted output]
I'm trying to sum the dynamically created solumn - Total_Income,
it keeps giving me almost-random errors,
would appreciate any help!
select
Cu.CustomerNum, Cu.Name, sum(Cio1.Quantity * C1.Price) AS Total_Income
from
Orders O1
inner join
CoursesInOrder Cio1 on O1.OrderNum = Cio1.OrderNum
inner join
Customer Cu on Cu.CustomerNum = O1.CustomerNum
inner join
Course C1 on C1.CourseNum = Cio1.CourseNum
where
O1.CustomerNum in (select O.CustomerNum
from Course C
inner join CoursesInOrder Cio on C.CourseNum = Cio.CourseNum
inner join Orders O on O.OrderNum= Cio.OrderNum
where C.CourseNum = '99771'
and year(O.Shiftdate) = '2014'
group by O.CustomerNum
having count(O.CustomerNum) > 2)
Group by Cu.CustomerNum, Cu.Name

Sum from the different tables Sql server

I have couple of tables which stores amount and I want to group by and get sum - reason for the mutiple tables are nhibernate descriminators.
I am using Union all and works but query is very big.
I am using following query
SELECT CustomerAccountNumber,
vc.CustomerName,
SUM(PermAmount) AS PermAmount,
SUM(FreetextAmount) AS FreetextAmount,
(SUM(PermAmount) + SUM(FreetextAmount)) AS TotalAmountByCustomer
FROM
(
SELECT pp.CustomerAccountNumber,
pl.Amount AS PermAmount,
0 AS FreetextAmount
FROM dbo.PermanentPlacementTransactionLine pl
INNER JOIN dbo.TransactionLine tl ON pl.TransactionLineId = tl.Id
INNER JOIN dbo.PermanentPlacement pp ON pl.PermanentPlacementId = pp.Id
WHERE tl.CurrentStatus = 1
GROUP BY pp.CustomerAccountNumber,
pl.Amount,
tl.Id
UNION ALL
SELECT ft.CustomerAccountNumber,
0 AS PermAmount,
ft.Amount AS FreetextAmount
FROM dbo.FreeTextTransactionLine fttl
INNER JOIN dbo.TransactionLine tl ON fttl.TransactionLineId = tl.Id
INNER JOIN dbo.[FreeText] ft ON fttl.FreeTextId = ft.Id
WHERE tl.CurrentStatus = 1
GROUP BY ft.CustomerAccountNumber,
ft.Amount,
tl.Id
) WIPSummary
INNER JOIN dbo.vw_Customer vc ON WIPSummary.CustomerAccountNumber = vc.CustomerAccount
GROUP BY CustomerAccountNumber,
vc.CustomerName;
is there any elegant way of displaying amount in separate columns ?
I can use partition by if it was same table and want to display row by row.
Try these query, is easy to understand and probably faster than yours.
I assume that the values are unique in your view
WITH cte_a
AS (SELECT pp.customeraccountnumber
,Sum(pl.amount) AS PermAmount
,0 AS FreetextAmount
FROM dbo.permanentplacementtransactionline pl
INNER JOIN dbo.transactionline tl
ON pl.transactionlineid = tl.id
INNER JOIN dbo.permanentplacement pp
ON pl.permanentplacementid = pp.id
WHERE tl.currentstatus = 1
GROUP BY pp.customeraccountnumber),
cte_b
AS (SELECT ft.customeraccountnumber
,0 AS PermAmount
,Sum(ft.amount) AS FreetextAmount
FROM dbo.freetexttransactionline fttl
INNER JOIN dbo.transactionline tl
ON fttl.transactionlineid = tl.id
INNER JOIN dbo.[freetext] ft
ON fttl.freetextid = ft.id
WHERE tl.currentstatus = 1
GROUP BY ft.customeraccountnumber)
SELECT vc.customeraccountnumber
,vc.customername
,Isnull(A.permamount, 0) AS PermAmount
,Isnull(B.freetextamount, 0) AS FreetextAmount
,Isnull(A.permamount, 0)
+ Isnull(B.freetextamount, 0) AS TotalAmountByCustomer
FROM dbo.vw_customer vc
LEFT JOIN cte_a a
ON vc.customeraccount = A.customeraccountnumber
LEFT JOIN cte_b b
ON vc.customeraccount = A.customeraccountnumber
if no table structures and sample data, that is the best I can do to help you.

SQL - charges and payments in same column; how to break it out

I have a SQL query that is pulling data from multiple tables (I have 11 joins)
There is an "ARTransaction" table which contains charges, payments, adjustments, etc. and there is a "transactionCodeID" column inside of that which describes the type of transaction.
I am trying to select a lot of data, but need two separate columns(the ones with comments above them), one for charges and one for payments. Is there a way to achieve this without using the where clause? I tried to use a nested select statement but it returned the same value for every single row (the total amount)
I am attaching the query below - thanks in advance! Also I am fairly new to data retrieval so if anything else looks wonky any other advice is greatly appreciated.
SELECT CONVERT(varchar(10),sl.ServiceDtFrom, 101) AS 'srvdate'
, f.Alias AS 'svc dprtmnt'
, CASE WHEN pc.Alias IS NULL
THEN po.Name
ELSE pc.Description END AS 'svc dept grp'
, COUNT(clm.ID) AS 'clm cnt'
, COUNT(p.ID) AS 'ptnt count'
/* 1 */
, SUM(ar.Amount) AS 'all chgs' --ONLY CHARGES (tt.ID IN(1,2))
, SUM(sl.Units + sl.TimeUnits + sl.PhysicalStatusUnits) AS 'chg units sum'
/* 2 */
, SUM(ar.Amount) AS 'net pmt' --ONLY PAYMENTS (tt.ID IN(3,4,9,10,11,12,20,21))
FROM ARTransaction ar WITH (NOLOCK)
LEFT JOIN ServiceLine sl WITH (NOLOCK)
ON ar.ServiceLineID = sl.ID
LEFT JOIN Incident i WITH (NOLOCK)
ON sl.IncidentID = i.ID
LEFT JOIN HealthCareFacility f WITH (NOLOCK)
ON i.FacilityID = f.ID
LEFT JOIN ProvOrgFacility poc WITH (NOLOCK)
ON poc.FacilityID = f.ID
LEFT JOIN ProfitCenter pc WITH (NOLOCK)
ON poc.ProfitCenterID = pc.ID
LEFT JOIN ProviderOrganization po WITH (NOLOCK)
ON i.ProvOrgID = po.ID
LEFT JOIN Claim clm WITH (NOLOCK)
ON i.ID = clm.IncidentID
LEFT JOIN Person p WITH (NOLOCK)
ON i.PatientID = p.ID
LEFT JOIN TransactionCode tc WITH (NOLOCK)
ON ar.TransactionCodeID = tc.ID
LEFT JOIN TransactionType tt WITH (NOLOCK)
ON tc.TransactionTypeID = tt.ID
WHERE i.IsReversed <> 1
AND sl.ServiceDtFrom IS NOT NULL
GROUP BY
sl.ServiceDtFrom, f.Alias
, po.Name, pc.Alias, pc.Description
ORDER BY 1,3,2
You can use CASE statements to achieve this:-
SELECT CONVERT(varchar(10),sl.ServiceDtFrom, 101) AS 'srvdate'
, f.Alias AS 'svc dprtmnt'
, CASE WHEN pc.Alias IS NULL
THEN po.Name
ELSE pc.Description END AS 'svc dept grp'
, COUNT(clm.ID) AS 'clm cnt'
, COUNT(p.ID) AS 'ptnt count'
/* 1 */
, SUM(case when tt.ID IN(1,2) then ar.Amount else 0 end) AS 'all chgs' --ONLY CHARGES (tt.ID IN(1,2))
, SUM(sl.Units + sl.TimeUnits + sl.PhysicalStatusUnits) AS 'chg units sum'
/* 2 */
, SUM(case when tt.ID IN(3,4,9,10,11,12,20,21) then ar.Amount else 0 end) AS 'net pmt' --ONLY PAYMENTS (tt.ID IN(3,4,9,10,11,12,20,21))
FROM ARTransaction ar WITH (NOLOCK)
LEFT JOIN ServiceLine sl WITH (NOLOCK)
ON ar.ServiceLineID = sl.ID
LEFT JOIN Incident i WITH (NOLOCK)
ON sl.IncidentID = i.ID
LEFT JOIN HealthCareFacility f WITH (NOLOCK)
ON i.FacilityID = f.ID
LEFT JOIN ProvOrgFacility poc WITH (NOLOCK)
ON poc.FacilityID = f.ID
LEFT JOIN ProfitCenter pc WITH (NOLOCK)
ON poc.ProfitCenterID = pc.ID
LEFT JOIN ProviderOrganization po WITH (NOLOCK)
ON i.ProvOrgID = po.ID
LEFT JOIN Claim clm WITH (NOLOCK)
ON i.ID = clm.IncidentID
LEFT JOIN Person p WITH (NOLOCK)
ON i.PatientID = p.ID
LEFT JOIN TransactionCode tc WITH (NOLOCK)
ON ar.TransactionCodeID = tc.ID
LEFT JOIN TransactionType tt WITH (NOLOCK)
ON tc.TransactionTypeID = tt.ID
WHERE i.IsReversed <> 1
AND sl.ServiceDtFrom IS NOT NULL
GROUP BY

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.

SQL Statement Help Needed:Query within a Query

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')