How to link sql sub queries together? - sql

is it possible to link the following sub query (see below.) The first three sub queries work fine however I'm struggling to see how to do the rest any guidance would be great cheers.
Ps. apologies for the long code
SELECT c.[Status],
c.CompanyId,
c.Name,
(SELECT count(DISTINCT usr.UserID)
FROM [ondemand.10cms.com].Security.[user] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = Company.CompanyID
WHERE usr.CompanyID = c.CompanyID) AS TotalUsers,
(SELECT sum (CASE WHEN usr.Status = 2 THEN 1 ELSE 0 END)
FROM [ondemand.10cms.com].Security.[user] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = Company.CompanyID
WHERE usr.CompanyID = c.CompanyID) AS ActiveUsers,
(SELECT sum (CASE WHEN usr.Status = 3 THEN 1 ELSE 0 END)
FROM [ondemand.10cms.com].Security.[User] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = Company.CompanyID WHERE usr.CompanyID = c.CompanyID) AS SuspendedUsers,
(Select COUNT (distinct usrs.id)
From [ondemand.10cms.com].Security.UserSession usrs
inner join [ondemand.10cms.com].Security.[user] usr on usrs.UserID=usr.UserID
) as TotalLogin,
(Select
COUNT( MerchandisingModule.Name)
From [ondemand.10cms.com].Project.Template
inner join [ondemand.10cms.com].Project.MerchandisingModule on Template.TemplateID= MerchandisingModule.TemplateId
)as CurrentModules,
(Select
count(MerchandisingModule.CreatedDate)
from [ondemand.10cms.com].Project.MerchandisingModule
inner join [ondemand.10cms.com].Project.Template on Template.TemplateID= MerchandisingModule.TemplateId
)as ModulesCreated,
(Select
count(mm.UpdatedDate)
from [ondemand.10cms.com].Project.MerchandisingModule mm
inner join [ondemand.10cms.com].Project.Template on Template.TemplateID= mm.TemplateId
)as ModulesUpdated,
(Select
COUNT(MA.MerchandisingAreaID)
from [ondemand.10cms.com].Project.MerchandisingArea MA
inner join [ondemand.10cms.com].Project.Project on Project.ProjectID= MA.ProjectID
) as Currentareas,
(Select
COUNT (MA.name)
from [ondemand.10cms.com].Project.MerchandisingArea MA
inner join [ondemand.10cms.com].Project.Project on Project.ProjectID= MA.ProjectID
) as AreasCreated,
(select
COUNT (MerchandisingArea.UpdatedDate)
from [ondemand.10cms.com].Project.MerchandisingArea
inner join [ondemand.10cms.com].Project.Project on Project.ProjectID= MerchandisingArea.ProjectID
) as AreasUpdated,
(Select
SUM ( case when MA.PublishStatus = 1 then 1 else 0 end)
from [ondemand.10cms.com].Project.MerchandisingArea MA
inner join [ondemand.10cms.com].Project.PublishingStatus on PublishingStatus.PublishStatusId = MA.PublishStatus
) as SuccessPublished,
(Select
SUM ( case when MA.PublishStatus = 3 then 1 else 0 end)
from [ondemand.10cms.com].Project.MerchandisingArea MA
inner join [ondemand.10cms.com].Project.PublishingStatus on PublishingStatus.PublishStatusId= MA.PublishStatus
) as FailedPublished
from [ondemand.10cms.com].Company.Company c

This was fixed by adding another inner join to each sub query and also another where clause

Related

Joining two queries to one table and substracting values

i need to put those two output values (Add_sum and Minus_sum) to one table and subtract them (Add_sum - Minus_sum) and show this value.
I tried many other options, subqueries etc but could not get it to work.
Query 1:
SELECT I.ItemCode, COUNT(H.TransactionTypeID) AS ADD_Sum
FROM inMoveHd AS H INNER JOIN
inMoveLn AS L ON L.InvMoveID = H.InvMoveID INNER JOIN
inItem AS I ON I.ItemID = L.ItemID INNER JOIN
inTransactionType AS T ON H.TransactionTypeID = T.TransactionTypeID
WHERE (T.TransactionSign = 1)
GROUP BY I.ItemCode
Query 2:
SELECT I.ItemCode, COUNT(H.TransactionTypeID) AS Minus_Sum
FROM inMoveHd AS H INNER JOIN
inMoveLn AS L ON L.InvMoveID = H.InvMoveID INNER JOIN
inItem AS I ON I.ItemID = L.ItemID INNER JOIN
inTransactionType AS T ON H.TransactionTypeID = T.TransactionTypeID
WHERE (T.TransactionSign = -1)
GROUP BY I.ItemCode
Use case expressions to do conditional aggregation:
SELECT I.ItemCode,
COUNT(case when T.TransactionSign = 1 then H.TransactionTypeID end) AS ADD_Sum,
COUNT(case when T.TransactionSign = -1 then H.TransactionTypeID end) AS Minus_Sum
FROM inMoveHd AS H INNER JOIN
inMoveLn AS L ON L.InvMoveID = H.InvMoveID INNER JOIN
inItem AS I ON I.ItemID = L.ItemID INNER JOIN
inTransactionType AS T ON H.TransactionTypeID = T.TransactionTypeID
WHERE (T.TransactionSign = -1 or T.TransactionSign = 1)
GROUP BY I.ItemCode
I think that you are looking for conditional aggregation:
SELECT
I.ItemCode,
SUM(CASE WHEN T.TransactionSign = 1 THEN 1 ELSE 0 END) AS Add_Sum,
SUM(CASE WHEN T.TransactionSign = -1 THEN 1 ELSE 0 END) AS Minus_Sum,
SUM(T.TransactionSign) difference
FROM
inMoveHd AS H INNER JOIN
inMoveLn AS L ON L.InvMoveID = H.InvMoveID INNER JOIN
inItem AS I ON I.ItemID = L.ItemID INNER JOIN
inTransactionType AS T ON H.TransactionTypeID = T.TransactionTypeID
WHERE T.TransactionSign IN (-1, 1)
GROUP BY I.ItemCode

Finding the count

I have the following SQL query and need to know the count of companyid as I can see repeating data. How do I find the count of it. Following is the query
SELECT a.companyId 'companyId'
, i.orgDebtType 'orgDebtType'
, d.ratingTypeName 'ratingTypeName'
, c.currentRatingSymbol 'currentRatingSymbol'
, c.ratingStatusIndicator 'ratingStatusIndicator'
, g.qualifierValue 'qualifierValue'
, c.ratingdate 'ratingDate'
, h.value 'outlook'
FROM ciqRatingEntity a
JOIN ciqcompany com
on com.companyId = a.companyId
JOIN ciqratingobjectdetail b ON a.entitySymbolValue = b.objectSymbolValue
JOIN ciqRatingData c ON b.ratingObjectKey = c.ratingObjectKey
JOIN ciqRatingType d ON b.ratingTypeId = d.ratingTypeId
JOIN ciqRatingOrgDebtType i ON i.orgDebtTypeId=b.orgDebtTypeId
JOIN ciqRatingEntityData red ON red.entitySymbolValue=a.entitySymbolValue
AND red.ratingDataItemId='1' ---CoName
LEFT JOIN ciqRatingDataToQualifier f ON f.ratingDataId = c.ratingDataId
LEFT JOIN ciqRatingQualifiervalueType g ON g.qualifiervalueid = f.qualifierValueId
LEFT JOIN ciqRatingValueType h ON h.ratingValueId = c.outlookValueId
WHERE 1=1
AND b.ratingTypeId IN ( '130', '131', '126', '254' )
-- and a.companyId = #companyId
AND a.companyId IN
(SELECT distinct TOP 2000000
c.companyId
FROM ciqCompany c
inner join ciqCompanyStatusType cst on cst.companystatustypeid = c.companystatustypeid
inner join ciqCompanyType ct on ct.companyTypeId = c.companyTypeId
inner join refReportingTemplateType rep on rep.templateTypeId = c.reportingtemplateTypeId
inner join refCountryGeo rcg on c.countryId = rcg.countryId
inner join refState rs on rs.stateId = c.stateId
inner join ciqSimpleIndustry sc on sc.simpleIndustryId = c.simpleIndustryId
ORDER BY companyid desc)
ORDER BY companyId DESC, c.ratingdate, b.ratingTypeId, c.ratingStatusIndicator
This will list where there are duplicate companyID's
SELECT companyId, count(*) as Recs
FROM ciqCompany
GROUP BY ciqCompany
HAVING count(*) > 1
I understand that you wish to add a column to the query with the count of each companyId, you can use COUNT() OVER():
select count(a.companyId) over (partition by a.companyId) as companyCount,
<rest of the columns>
from ciqRatingEntity a
join <rest of the query>
This would return in each row the count of the companyId of that row without grouping the results.

Why doesn't my query return correct results?

I have used these Temp table to return total no of SOlved Cases and Total Number of Pending Cases from same table grouped by DIstrict e.g.
District TotalSolvedCases TotalPendingCases
A 3 1
B 8 6
C 7 1
I have done this but this doesn't return correct Result
SELECT *
INTO #Table1
FROM (
SELECT COUNT(Cases.pk_Cases_CaseID) TotalCases,
Districts.DistrictName
FROM Cases
INNER JOIN ConcernedOffices ON ConcernedOffices.pk_ConcernedOffices_ID = Cases.fk_ConcernedOffices_Cases_ConcernedOfficeID
INNER JOIN Districts ON Districts.pk_Districts_DistrictID = ConcernedOffices.fk_Districts_ConcernedOffices_DistrictID
INNER JOIN CaseHearings ON CaseHearings.fk_Cases_CaseHearings_CaseID = Cases.pk_Cases_CaseID
WHERE CaseHearings.IsClosingDate = 1
GROUP BY Districts.DistrictName
) d
SELECT *
INTO #Table2
FROM (
SELECT COUNT(Cases.pk_Cases_CaseID) TotalPedningCases,
Districts.DistrictName
FROM Cases
INNER JOIN ConcernedOffices ON ConcernedOffices.pk_ConcernedOffices_ID = Cases.fk_ConcernedOffices_Cases_ConcernedOfficeID
INNER JOIN Districts ON Districts.pk_Districts_DistrictID = ConcernedOffices.fk_Districts_ConcernedOffices_DistrictID
INNER JOIN CaseHearings ON CaseHearings.fk_Cases_CaseHearings_CaseID = Cases.pk_Cases_CaseID
WHERE CaseHearings.IsClosingDate = 0
GROUP BY Districts.DistrictName
) d
SELECT #Table1.TotalCases AS TotalSolvedCases,
#Table2.TotalPedningCases,
#Table1.DistrictName
FROM #Table1
INNER JOIN #Table2 ON #Table2.DistrictName = #Table1.DistrictName
GROUP BY #Table1.TotalCases,
#Table2.TotalPedningCases,
#Table1.DistrictName
You only need one SELECT, use case expressions to do conditional counting:
SELECT COUNT(case when CaseHearings.IsClosingDate = 1 then 1 end) TotalCases,
COUNT(case when CaseHearings.IsClosingDate = 0 then 1 end) TotalPedningCases,
Districts.DistrictName
FROM Cases
INNER JOIN ConcernedOffices ON ConcernedOffices.pk_ConcernedOffices_ID = Cases.fk_ConcernedOffices_Cases_ConcernedOfficeID
INNER JOIN Districts ON Districts.pk_Districts_DistrictID = ConcernedOffices.fk_Districts_ConcernedOffices_DistrictID
INNER JOIN CaseHearings ON CaseHearings.fk_Cases_CaseHearings_CaseID = Cases.pk_Cases_CaseID
GROUP BY Districts.DistrictName

Sub sum query bringing back more results then possible

I am currently running the following query.( See below) However when I run this query the active users and Suspended users are bring back a far greater result then that's in the database.
I just wondered if you could possibly shed light on the reason why and correct me where I'm going wrong?
SELECT c.[Status],
c.CompanyId,
c.Name,
(SELECT count(DISTINCT usr.UserID)
FROM [ondemand.10cms.com].Security.[user] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = c.CompanyID) AS TotalUsers,
(SELECT sum (CASE
WHEN usr.Status = 2 THEN 1
ELSE 0
END)
FROM [ondemand.10cms.com].Security.[user] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = c.CompanyID) AS ActiveUsers,
(SELECT sum (CASE
WHEN usr.Status = 3 THEN 1
ELSE 0
END)
FROM [ondemand.10cms.com].Security.[User] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = c.CompanyID) AS SuspendedUsers
FROM [ondemand.10cms.com].Company.Company c
In each of your sub queries you have two tables, one is being joined to the outer query but there is no join between the two inner tables. All of those sub queries are a bit unnecessary, I would rewrite as a simpler query, something like so:
SELECT
Company.[Status]
,Company.CompanyId
,Company.Name
,COUNT(DISTINCT usr.UserID) AS TotalUsers
,SUM(CASE WHEN usr.Status = 2 THEN 1
ELSE 0
END) AS ActiveUsers
,SUM(CASE WHEN usr.Status = 3 THEN 1
ELSE 0
END) AS SuspendedUsers
FROM [ondemand.10cms.com].Security.[user] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = Company.CompanyID
GROUP BY
Company.[Status]
,Company.CompanyId
,Company.Name
If you just wabt a fix for your query as is then try this:
SELECT c.[Status],
c.CompanyId,
c.Name,
(SELECT count(DISTINCT usr.UserID)
FROM [ondemand.10cms.com].Security.[user] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = Company.CompanyID
WHERE usr.CompanyID = c.CompanyID) AS TotalUsers,
(SELECT sum (CASE
WHEN usr.Status = 2 THEN 1
ELSE 0
END)
FROM [ondemand.10cms.com].Security.[user] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = Company.CompanyID
WHERE usr.CompanyID = c.CompanyID) AS ActiveUsers,
(SELECT sum (CASE
WHEN usr.Status = 3 THEN 1
ELSE 0
END)
FROM [ondemand.10cms.com].Security.[User] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = Company.CompanyID
WHERE usr.CompanyID = c.CompanyID) AS SuspendedUsers
FROM [ondemand.10cms.com].Company.Company c
I don't know your data (it could cause duplicates), but couldnt you use a standard group by and not use sub queries?
Select
c.[Status],
c.CompanyId,
c.Name,
count(distinct usr.UserID) as TotalUsers,
sum(case when usr.Status = 2 then 1 else 0 end) as ActiveUsers,
sum(case when usr.Status = 3 then 1 else 0 end) as SuspendedUsers
from [ondemand.10cms.com].Company.Company c
inner join [ondemand.10cms.com].Security.[user] usr
on usr.CompanyID=c.CompanyID
GROUP BY
c.[Status],
c.CompanyId,
c.Name
Try adding a group by CompanyId and let us know how that worked.

Query for logistic regression, multiple where exists

A logistic regression is a composed of a uniquely identifying number, followed by multiple binary variables (always 1 or 0) based on whether or not a person meets certain criteria. Below I have a query that lists several of these binary conditions. With only four such criteria the query takes a little longer to run than what I would think. Is there a more efficient approach than below? Note. tblicd is a large table lookup table with text representations of 15k+ rows. The query makes no real sense, just a proof of concept. I have the proper indexes on my composite keys.
select patient.patientid
,case when exists
(
select c.patientid from tblclaims as c
inner join patient as p on p.patientid=c.patientid
and c.admissiondate = p.admissiondate
and c.dischargedate = p.dischargedate
where patient.patientid = p.patientid
group by c.patientid
having count(*) > 1000
)
then '1' else '0'
end as moreThan1000
,case when exists
(
select c.patientid from tblclaims as c
inner join patient as p on p.patientid=c.patientid
and c.admissiondate = p.admissiondate
and c.dischargedate = p.dischargedate
where patient.patientid = p.patientid
group by c.patientid
having count(*) > 1500
)
then '1' else '0'
end as moreThan1500
,case when exists
(
select distinct picd.patientid from patienticd as picd
inner join patient as p on p.patientid= picd.patientid
and picd.admissiondate = p.admissiondate
and picd.dischargedate = p.dischargedate
inner join tblicd as t on t.icd_id = picd.icd_id
where t.descrip like '%diabetes%' and patient.patientid = picd.patientid
)
then '1' else '0'
end as diabetes
,case when exists
(
select r.patientid, count(*) from patient as r
where r.patientid = patient.patientid
group by r.patientid
having count(*) >1
)
then '1' else '0'
end
from patient
order by moreThan1000 desc
I would start by using subqueries in the from clause:
select q.patientid, moreThan1000, moreThan1500,
(case when d.patientid is not null then 1 else 0 end),
(case when pc.patientid is not null then 1 else 0 end)
from patient p left outer join
(select c.patientid,
(case when count(*) > 1000 then 1 else 0 end) as moreThan1000,
(case when count(*) > 1500 then 1 else 0 end) as moreThan1500
from tblclaims as c inner join
patient as p
on p.patientid=c.patientid and
c.admissiondate = p.admissiondate and
c.dischargedate = p.dischargedate
group by c.patientid
) q
on p.patientid = q.patientid left outer join
(select distinct picd.patientid
from patienticd as picd inner join
patient as p
on p.patientid= picd.patientid and
picd.admissiondate = p.admissiondate and
picd.dischargedate = p.dischargedate inner join
tblicd as t
on t.icd_id = picd.icd_id
where t.descrip like '%diabetes%'
) d
on p.patientid = d.patientid left outer join
(select r.patientid, count(*) as cnt
from patient as r
group by r.patientid
having count(*) >1
) pc
on p.patientid = pc.patientid
order by 2 desc
You can then probably simplify these subqueries more by combining them (for instance "p" and "pc" on the outer query can be combined into one). However, without the correlated subqueries, SQL Server should find it easier to optimize the queries.
Example of left joins as requested...
SELECT
patientid,
ISNULL(CondA.ConditionA,0) as IsConditionA,
ISNULL(CondB.ConditionB,0) as IsConditionB,
....
FROM
patient
LEFT JOIN
(SELECT DISTINCT patientid, 1 as ConditionA from ... where ... ) CondA
ON patient.patientid = CondA.patientID
LEFT JOIN
(SELECT DISTINCT patientid, 1 as ConditionB from ... where ... ) CondB
ON patient.patientid = CondB.patientID
If your Condition queries only return a maximum one row, you can simplify them down to
(SELECT patientid, 1 as ConditionA from ... where ... ) CondA