OK, I need somehelp. I have the following two queries:
SELECT DA.OWNG_OCD AS OFFICE, 'FL' AS STATE, SUM(S.STK_END_SEQ_NUM -
S.STK_STRT_SEQ_NUM) + COUNT(*) AS TOTSTK FROM STKRNG S, DFACCT DA, CMPNT C
WHERE RANGE_USED_SW = 'N' AND S.DFTACCT_CANUM = DA.DFTACCT_CANUM
AND DA.OWNG_OCD = C.OCD AND C.ST = 'FL' AND S.STK_TYP = 'R' GROUP
BY DA.OWNG_OCD;
AND
SELECT C.OCD, COUNT(*) AS USED FROM DRAFT D
JOIN STKRNG S ON S.DFTACCT_CANUM = D.DFTACCT_CANUM
JOIN DFACCT DA ON S.DFTACCT_CANUM = DA.DFTACCT_CANUM
JOIN CMPNT C ON CMPNT.OCD = DA.OWNG_OCD
WHERE D.DRFT_SEQ_NUM >= (SELECT MIN(S.STK_STRT_SEQ_NUM) FROM STKRNG S
WHERE D.DFTACCT_CANUM = S.DFTACCT_CANUM AND S.RANGE_USED_SW = 'N')
AND D.DRFT_SEQ_NUM <= (SELECT MAX(S.STK_END_SEQ_NUM) FROM STKRNG S WHERE
D.DFTACCT_CANUM = S.DFTACCT_CANUM AND S.RANGE_USED_SW = 'N')
AND S.STK_TYP = 'R'
AND S.RANGE_USED_SW = 'N'
AND C.ST = 'FL'
GROUP BY C.OCD;
I am trying to write one query where the results of the COUNT in the second query are subtracted from the results of the COUNT in the first query. Any idea on how to do this?
Put your queries in the from clause of your final query:
select q1.totstk - q2.used
from ( <your first query here> ) q1
join ( <your second query here> ) q2 on q2.ocd = q1.office;
try Something like this:
with STKRNGMINMAX as (
SELECT S.DFTACCT_CANUM,
MIN(S.STK_STRT_SEQ_NUM) MINNUM, MAX(S.STK_END_SEQ_NUM) MAXNUM,
SUM(S.STK_END_SEQ_NUM - S.STK_STRT_SEQ_NUM) DIFFNUM
FROM STKRNG S
WHERE (S.RANGE_USED_SW, S.STK_TYP)=('N', 'R')
group by S.DFTACCT_CANUM
)
SELECT C.OCD, S.DIFFNUM - COUNT(*) AS TOTSTK,
FROM DRAFT D
INNER JOIN STKRNGMINMAX S ON S.DFTACCT_CANUM = D.DFTACCT_CANUM and D.DRFT_SEQ_NUM between S.MINNUM AND S.MAXNUM
INNER JOIN DFACCT DA ON S.DFTACCT_CANUM = DA.DFTACCT_CANUM
INNER JOIN CMPNT C ON C.OCD = DA.OWNG_OCD and C.ST='FL'
GROUP BY C.OCD;
Related
I want to select only the first record from each group. So basically I only want the data for first processing date column and don't want the rest of the date for each product.
My current code as below
SELECT
C.AccountID as ABN_ACC ,
C.ProductSymbol,
C.ProductShortName,
S.ReactorProduct AS REC_PROD,
C.CurrencyCode AS PROD_CCY,
C.CountryOfPayment AS PAYCONTRY,
C.DividendValueCur AS PAYCCY,
C.DividendValue AS DIV_AMNT,
CONCAT ((IIF (C.QuantitySettledNoTax_LS = 'S' ,(-1*C.QuantitySettledNoTax),C.QuantitySettledNoTax )),(IIF(C.QuantitySettledTax_LS = 'S',(-1*C.QuantitySettledTax),QuantitySettledTax))) AS DIVQTY ,
C.ExdividendDate AS EXDATE,
C.Recorddate AS RECDATE,
C.DividendPayDate AS PAYDATE
From "LiquidCDW". [Staging].[CA_CorporateActions] AS C
RIGHT JOIN "LiquidCDW".[Staging].[POS_SettledPositions] AS P ON C.Recorddate = P.ProcessingDate AND C.AccountID = p.AccountID AND C.ProductSymbol = P.ProductSymbol AND C.DividendValueCur = P.CurrencyCode
INNER JOIN "LiquidCDW".[Transformation].[Mapping_Product_ABNReactor] AS S ON C.ProductSymbol = S.ReactorProduct AND S.ValidTo IS NULL AND S.ProductType = 'E' AND c.DividendValueCur = S.Currency
where C.ExdividendDate >= '20210201'
ORDER by C.ProductSymbol , C.CurrencyCode
One approach uses ROW_NUMBER:
WITH cte AS (
SELECT
ROW_NUMBER() OVER (PARTITION BY C.ProductSymbol ORDER BY processingDate) rn,
C.AccountID AS ABN_ACC,
C.ProductSymbol,
C.ProductShortName,
S.ReactorProduct AS REC_PROD,
C.CurrencyCode AS PROD_CCY,
C.CountryOfPayment AS PAYCONTRY,
C.DividendValueCur AS PAYCCY,
C.DividendValue AS DIV_AMNT,
CONCAT((IIF(C.QuantitySettledNoTax_LS = 'S',
(-1*C.QuantitySettledNoTax), C.QuantitySettledNoTax)),
(IIF(C.QuantitySettledTax_LS = 'S',
(-1*C.QuantitySettledTax),QuantitySettledTax))) AS DIVQTY,
C.ExdividendDate AS EXDATE,
C.Recorddate AS RECDATE,
C.DividendPayDate AS PAYDATE
FROM [LiquidCDW].[Staging].[CA_CorporateActions] AS C
RIGHT JOIN "LiquidCDW".[Staging].[POS_SettledPositions] AS P
ON C.Recorddate = P.ProcessingDate AND
C.AccountID = p.AccountID AND
C.ProductSymbol = P.ProductSymbol AND
C.DividendValueCur = P.CurrencyCode
INNER JOIN [LiquidCDW].[Transformation].[Mapping_Product_ABNReactor] AS S
ON C.ProductSymbol = S.ReactorProduct AND
S.ValidTo IS NULL AND
S.ProductType = 'E' AND
C.DividendValueCur = S.Currency
WHERE
C.ExdividendDate >= '20210201'
)
SELECT *
FROM cte
WHERE rn = 1
ORDER BY ProductSymbol, CurrencyCode;
I have a query with a lot of tables and joins. So a simple Count(column) and Group By isn't working correctly.
The query returns an item list. I want to calculate how many times each item appears in that list.
Here's my query:
SELECT DECODE(BOM.ORGANIZATION_ID,203, 'CEC', 328, '3PL', 204, 'SIM') ORGANIZATION_CODE,
BOM.ORGANIZATION_ID,
MSI.SEGMENT1 "PARENT_ITEM",
MSIC.SEGMENT1 "COMPONENT_ITEM",
SUM(NVL(MMT.TRANSACTION_QUANTITY,0)) * NVL(SUM(CIC.ITEM_COST),0) "ANNUAL_MONEY",
SUM(NVL(MMT.TRANSACTION_QUANTITY,0)) "ANNUAL_QTY_USG",
NVL(SUM(CIC.ITEM_COST),0) "AVG_COST",
SUM(NVL(MSI.POSTPROCESSING_LEAD_TIME,0) + NVL(MSI.PREPROCESSING_LEAD_TIME,0)) LEAD_TIME
FROM BOM_BILL_OF_MATERIALS BOM
LEFT JOIN MTL_SYSTEM_ITEMS MSI
ON MSI.ORGANIZATION_ID = BOM.ORGANIZATION_ID
AND MSI.INVENTORY_ITEM_ID = BOM.ASSEMBLY_ITEM_ID
AND MSI.ENABLED_FLAG = 'Y'
AND MSI.BOM_ENABLED_FLAG = 'Y'
LEFT JOIN CST_ITEM_COSTS CIC
ON CIC.ORGANIZATION_ID = BOM.ORGANIZATION_ID
AND CIC.INVENTORY_ITEM_ID = BOM.ASSEMBLY_ITEM_ID
AND CIC.COST_TYPE_ID = 1
LEFT JOIN MTL_MATERIAL_TRANSACTIONS MMT
ON MMT.INVENTORY_ITEM_ID = BOM.ASSEMBLY_ITEM_ID
AND MMT.ORGANIZATION_ID = BOM.ORGANIZATION_ID
AND MMT.TRANSACTION_TYPE_ID IN (33,34,17)
LEFT JOIN MTL_TRANSACTION_TYPES MTT
ON MTT.TRANSACTION_TYPE_ID = MTT.TRANSACTION_TYPE_ID
LEFT JOIN BOM_INVENTORY_COMPONENTS BIC
ON BIC.BILL_SEQUENCE_ID = BOM.COMMON_BILL_SEQUENCE_ID
AND NVL(bic.disable_date, sysdate+1) > sysdate
LEFT JOIN BOM_COMPONENTS_B BCB
ON BIC.COMPONENT_SEQUENCE_ID = BCB.COMPONENT_SEQUENCE_ID
LEFT JOIN BOM_STRUCTURES_B BSB
ON BCB.BILL_SEQUENCE_ID = BSB.BILL_SEQUENCE_ID
LEFT JOIN MFG_LOOKUPS ML
ON ML.LOOKUP_CODE = BIC.WIP_SUPPLY_TYPE
AND ML.LOOKUP_CODE = BIC.ENFORCE_INT_REQUIREMENTS
AND ML.LOOKUP_TYPE = 'MTL_EAM_ITEM_TYPE'
LEFT JOIN MTL_SYSTEM_ITEMS MSIC
ON MSIC.ORGANIZATION_ID = BOM.ORGANIZATION_ID
AND MSIC.INVENTORY_ITEM_ID = BIC.COMPONENT_ITEM_ID
LEFT JOIN BOM_OPERATIONAL_ROUTINGS BOR
ON BOR.ASSEMBLY_ITEM_ID = BOM.ASSEMBLY_ITEM_ID
AND BOR.ORGANIZATION_ID = BOM.ORGANIZATION_ID
WHERE BOM.ORGANIZATION_ID = NVL(:P_ORG_ID,BOM.ORGANIZATION_ID)
AND EXISTS
(SELECT 'X'
FROM MTL_MATERIAL_TRANSACTIONS MMT
WHERE MMT.TRANSACTION_DATE >= ADD_MONTHS (SYSDATE,-12)
AND MSI.INVENTORY_ITEM_ID IS NOT NULL
)
GROUP BY BOM.ORGANIZATION_ID,
MSI.SEGMENT1,
MSIC.SEGMENT1
ORDER BY ORGANIZATION_CODE,
MSIC.SEGMENT1
My output is like this now:
I want to have another column which counts each item occurence in the output.
That's called conditional aggregation and you can do it with CASE EXPRESSION :
SELECT <col1>,<col2>..,
COUNT(CASE WHEN column ='Specific Val' THEN 1 END) as cnt
FROM YourTable
GROUP BY <col1>,<col2>..,
In MySQL this is also fine:
SUM(column = 'Specific Val')
Because expressions are treated as 1 and 0 .
wouldn't count(distinct column) work here since you're already using a group by
Would this be what you are looking for:
SELECT ColumnName, COUNT(*)
FROM TableName
GROUP BY ColumnName;
On the location of TableName you can also use a (SELECT ....).
You can also try this:
select count(*) from
(your query)
where column='value to be checked'
The below query is to retrieve the records whose (SGT_DISBURSEMENT_REQUEST) count is only one. It is working great. But performance wise it didn't took so much of time since we have 100 000 records.
Is there any better way to do it?
SELECT PA.PERSON_ID,
PA.PERSON_ACCOUNT_ID,
DR.DISBURSEMENT_REQUEST_ID,
SUM
(
ISNULL(CD.EE_PRE_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_PRE_TAX_AMT,0)
) AS EE_PRE_TAX_CONTRIB,
DD.PRE_TAX_AMOUNT AS DISB_DTL_PRE_TAX_AMOUNT,
SUM
( ISNULL(CD.EE_POST_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_POST_TAX_AMT,0)
) AS EE_POST_TAX_CONTRIB,
DD.POST_TAX_AMOUNT AS DISB_DTL_POST_TAX_AMOUNT
FROM SGT_DISBURSEMENT_REQUEST DR
INNER JOIN SGT_DISBURSEMENT_DETAIL DD ON DR.DISBURSEMENT_REQUEST_ID = DD.DISBURSEMENT_REQUEST_ID
INNER JOIN SGT_PERSON_ACCOUNT PA ON PA.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID
INNER JOIN SGT_CONTRIB_DTL CD ON CD.PERSON_ACCOUNT_ID = PA.PERSON_ACCOUNT_ID
WHERE DR.REQUEST_CATEGORY_VALUE = 'REFD' AND
DD.DETAIL_CATEGORY_VALUE = 'REFD' AND
CD.STATUS_VALUE = 'VALD' AND
CD.POSTED_DATE <= DR.ACCEPTED_TO_PAYROLL_DATE AND
DR.DISBURSEMENT_STATUS_VALUE <> 'CANL' AND
EXISTS
(
SELECT 1 FROM SGT_DISBURSEMENT_REQUEST SDR1
INNER JOIN SGT_DISBURSEMENT_DETAIL SDD1 ON SDD1.DISBURSEMENT_REQUEST_ID = SDR1.DISBURSEMENT_REQUEST_ID
WHERE SDR1.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID and SDD1.DETAIL_CATEGORY_VALUE = DD.DETAIL_CATEGORY_VALUE
GROUP BY SDR1.PERSON_ACCOUNT_ID
HAVING COUNT(*) = 1
)
GROUP BY
PA.PERSON_ID, PA.PERSON_ACCOUNT_ID, DR.DISBURSEMENT_REQUEST_ID, DD.PRE_TAX_AMOUNT, DD.POST_TAX_AMOUNT
For Performance improvement you can have the Filter Conditions in the Join Clause, instead of where clause. In this case each join will restrict the results to even lesser number of rows.
SELECT PA.PERSON_ID,
PA.PERSON_ACCOUNT_ID,
DR.DISBURSEMENT_REQUEST_ID,
SUM
(
ISNULL(CD.EE_PRE_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_PRE_TAX_AMT,0)
) AS EE_PRE_TAX_CONTRIB,
DD.PRE_TAX_AMOUNT AS DISB_DTL_PRE_TAX_AMOUNT,
SUM
( ISNULL(CD.EE_POST_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_POST_TAX_AMT,0)
) AS EE_POST_TAX_CONTRIB,
DD.POST_TAX_AMOUNT AS DISB_DTL_POST_TAX_AMOUNT
FROM SGT_DISBURSEMENT_REQUEST DR
INNER JOIN SGT_DISBURSEMENT_DETAIL DD ON DR.DISBURSEMENT_REQUEST_ID = DD.DISBURSEMENT_REQUEST_ID AND DR.REQUEST_CATEGORY_VALUE = 'REFD' AND
DD.DETAIL_CATEGORY_VALUE = 'REFD' AND DR.DISBURSEMENT_STATUS_VALUE <> 'CANL'
INNER JOIN SGT_PERSON_ACCOUNT PA ON PA.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID
INNER JOIN SGT_CONTRIB_DTL CD ON CD.PERSON_ACCOUNT_ID = PA.PERSON_ACCOUNT_ID AND CD.STATUS_VALUE = 'VALD' AND
CD.POSTED_DATE <= DR.ACCEPTED_TO_PAYROLL_DATE
WHERE EXISTS
(
SELECT 1 FROM SGT_DISBURSEMENT_REQUEST SDR1
INNER JOIN SGT_DISBURSEMENT_DETAIL SDD1 ON SDD1.DISBURSEMENT_REQUEST_ID = SDR1.DISBURSEMENT_REQUEST_ID
WHERE SDR1.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID and SDD1.DETAIL_CATEGORY_VALUE = DD.DETAIL_CATEGORY_VALUE
GROUP BY SDR1.PERSON_ACCOUNT_ID
HAVING COUNT(*) = 1
)
GROUP BY
PA.PERSON_ID, PA.PERSON_ACCOUNT_ID, DR.DISBURSEMENT_REQUEST_ID, DD.PRE_TAX_AMOUNT, DD.POST_TAX_AMOUNT
if you use count over it should give you the same result and be better for performance:
select * from (
SELECT PA.PERSON_ID,
PA.PERSON_ACCOUNT_ID,
DR.DISBURSEMENT_REQUEST_ID,
SUM
(
ISNULL(CD.EE_PRE_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_PRE_TAX_AMT,0)
) AS EE_PRE_TAX_CONTRIB,
DD.PRE_TAX_AMOUNT AS DISB_DTL_PRE_TAX_AMOUNT,
SUM
( ISNULL(CD.EE_POST_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_POST_TAX_AMT,0)
) AS EE_POST_TAX_CONTRIB,
DD.POST_TAX_AMOUNT AS DISB_DTL_POST_TAX_AMOUNT
,count(*) over(partition by PA.PERSON_ACCOUNT_ID ) as ct
FROM SGT_DISBURSEMENT_REQUEST DR
INNER JOIN SGT_DISBURSEMENT_DETAIL DD ON DR.DISBURSEMENT_REQUEST_ID = DD.DISBURSEMENT_REQUEST_ID
INNER JOIN SGT_PERSON_ACCOUNT PA ON PA.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID
INNER JOIN SGT_CONTRIB_DTL CD ON CD.PERSON_ACCOUNT_ID = PA.PERSON_ACCOUNT_ID
WHERE DR.REQUEST_CATEGORY_VALUE = 'REFD' AND
DD.DETAIL_CATEGORY_VALUE = 'REFD' AND
CD.STATUS_VALUE = 'VALD' AND
CD.POSTED_DATE <= DR.ACCEPTED_TO_PAYROLL_DATE AND
DR.DISBURSEMENT_STATUS_VALUE <> 'CANL'
GROUP BY
PA.PERSON_ID, PA.PERSON_ACCOUNT_ID, DR.DISBURSEMENT_REQUEST_ID, DD.PRE_TAX_AMOUNT, DD.PRE_TAX_AMOUNT, DD.POST_TAX_AMOUNT
) as x
where x.ct = 1
I would materialize this to a #temp
SELECT DR1.PERSON_ACCOUNT_ID, SDD1.DETAIL_CATEGORY_VALUE
FROM SGT_DISBURSEMENT_REQUEST SDR1
JOIN SGT_DISBURSEMENT_DETAIL SDD1
ON SDD1.DISBURSEMENT_REQUEST_ID = SDR1.DISBURSEMENT_REQUEST_ID
GROUP BY SDR1.PERSON_ACCOUNT_ID, SDD1.DETAIL_CATEGORY_VALUE
HAVING COUNT(*) = 1
join #temp
on #temp.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID
and #temp.DETAIL_CATEGORY_VALUE = DD.DETAIL_CATEGORY_VALUE
I've got the following query:
SELECT DISTINCT CU.permit_id, CU.month, /*CU.year,*/ M.material_id, M.material_name, /*MC.chemical_id, C.chemical_name,
C.precursor_organic_compound, C.non_precursor_organic_compound,*/
/*MC.chemical_percentage,*/
POC_emissions =
CASE
WHEN (C.precursor_organic_compound = 'true')
THEN (CU.chemical_usage_lbs / CU.material_density) * M.VOC
ELSE 0
END,
NON_POC_emissions =
CASE
WHEN (C.non_precursor_organic_compound = 'true')
THEN CU.chemical_usage_lbs * (MC.chemical_percentage / 100)
ELSE 0
END
FROM material M
LEFT OUTER JOIN material_chemical MC ON MC.material_id = M.material_id
LEFT OUTER JOIN chemical_usage CU ON CU.material_id = MC.material_id
LEFT OUTER JOIN chemical C ON C.chemical_id = MC.chemical_id
WHERE (CU.month >=1 AND CU.month <= 2)
AND CU.year = 2013
AND M.material_id = 52
--AND CU.permit_id = 2118
--GROUP BY CU.permit_id, M.material_id, M.material_name, CU.month, MC.chemical_id, MC.chemical_id, C.chemical_name, C.precursor_organic_compound, C.non_precursor_organic_compound
--ORDER BY C.chemical_name ASC
Which returns:
But what I need is to return one row per month per material adding up the values of POC per month and NON_POC per month.
So, I should end up with something like:
Month material_id material_name POC NON_POC
1 52 Krylon... 0.107581 0.074108687
2 52 Krylon... 0.143437 0.0988125
I tried using SUM but it sums up the same result multiple times:
SELECT /*DISTINCT*/ CU.permit_id, CU.month, /*CU.year,*/ M.material_id, M.material_name, /*MC.chemical_id, C.chemical_name,
C.precursor_organic_compound, C.non_precursor_organic_compound,*/
--MC.chemical_percentage,
POC_emissions = SUM(
CASE
WHEN (C.precursor_organic_compound = 'true')
THEN (CU.chemical_usage_lbs / CU.material_density) * M.VOC
ELSE 0
END),
NON_POC_emissions = SUM(
CASE
WHEN (C.non_precursor_organic_compound = 'true')
THEN CU.chemical_usage_lbs * (MC.chemical_percentage / 100)
ELSE 0
END)
FROM material M
LEFT OUTER JOIN material_chemical MC ON MC.material_id = M.material_id
LEFT OUTER JOIN chemical_usage CU ON CU.material_id = MC.material_id
LEFT OUTER JOIN chemical C ON C.chemical_id = MC.chemical_id
WHERE M.material_id = 52
--AND CU.permit_id = 187
AND (CU.month >=1 AND CU.month <= 2)
AND CU.year = 2013
GROUP BY CU.permit_id, M.material_id, M.material_name, CU.month/*, CU.year, MC.chemical_id, C.chemical_name, C.precursor_organic_compound, C.non_precursor_organic_compound*/
--ORDER BY C.chemical_name ASC
The first query has a DISTINCT clause. What is the output without the DISTINCT clause. I suspect you have more rows than shows in your screenshot.
Regardless, you could try something like this to get the desired result.
select permit_id, month, material_id, material_name,
sum(poc_emissions), sum(non_poc_emissions)
from (
SELECT DISTINCT CU.permit_id, CU.month, M.material_id, M.material_name,
POC_emissions =
CASE
WHEN (C.precursor_organic_compound = 'true')
THEN (CU.chemical_usage_lbs / CU.material_density) * M.VOC
ELSE 0
END,
NON_POC_emissions =
CASE
WHEN (C.non_precursor_organic_compound = 'true')
THEN CU.chemical_usage_lbs * (MC.chemical_percentage / 100)
ELSE 0
END
FROM material M
LEFT OUTER JOIN material_chemical MC ON MC.material_id = M.material_id
LEFT OUTER JOIN chemical_usage CU ON CU.material_id = MC.material_id
LEFT OUTER JOIN chemical C ON C.chemical_id = MC.chemical_id
WHERE (CU.month >=1 AND CU.month <= 2)
AND CU.year = 2013
AND M.material_id = 52
) main
group by permit_id, month, material_id, material_name
Explanation
Since the results you retrieved by doing a DISTINCT was consider source-of-truth, I created an in-memory table by making it a sub-query. However, this subquery must have a name of some kind...whatever name. I gave it a name main. Subqueries look like this:
select ... from (sub-query) <give-it-a-table-name>
Simple Example:
select * from (select userid, username from user) user_temp
Advanced Example:
select * from (select userid, username from user) user_temp
inner join (select userid, sum(debits) as totaldebits from debittable) debit
on debit.userid = user_temp.userid
Notice how user_temp alias for the subquery can be used as if the sub-query was a real table.
Use above query in subquery and group by (month) and select sum(POC_emissions) and sum(NON_POC_emissions )
I have code to select some applications but LEFT JOIN is creating duplicates.
Question: How to get rid of duplicates generated by
LEFT JOIN
attachments as att
ON
(a.ssn = att.ssn AND att.doc_type = 'id_copy' AND att.source = 'cpt3')
My Work:
I am considering SELECT DISTINCT or GROUP BY but, can't figure out where to put them.
This is the query:
SELECT
a.*, c.code, l.who, l.locked_time, att.id AS attnew,
( SELECT
COUNT(*)
FROM
applications as a2
WHERE
a2.approved = 'Y'
AND
a2.paid = 'Y'
AND
a2.paid_back = 'Y'
AND
a2.ssn = a.ssn
) AS previous_apps
FROM
applications as a
LEFT JOIN
locked_by as l
USING(id)
LEFT JOIN
campaign_codes as c
ON
c.id = a.campaign
LEFT JOIN
attachments as att
ON
(a.ssn = att.ssn AND att.doc_type = 'id_copy' AND att.source = 'cpt3')
WHERE
a.closed='N'
AND
a.paid = 'N'
ORDER BY
a.arrived_date
DESC
Use GROUP BY
to avoid duplicates. In your case:
...
WHERE
a.closed='N'
AND
a.paid = 'N'
GROUP BY
a.id
ORDER BY
a.arrived_date
DESC
If you want to make an one to one relation to avoid duplicates and att.id is the same for each att.ssn or you need only one (MAX,MIN,..ANY?) att.id. Try this:
LEFT JOIN
(SELECT ssn,
MAX(id) as id,
FROM attachments
WHERE doc_type = 'id_copy' AND source = 'cpt3'
GROUP BY ssn
)as att
ON
(a.ssn = att.ssn)