Get count from table given input from another - sql

I have 3 tables: filer_info, filer_persent and persent_email, connected via:
filer_info.filer_info_id = filer_persent.filer_info_id
filer_persent.persent_info_id = persent_email.persent_info_id
I want to find all rows where I have multiple type PRIMARY in the persent_email table (ie count > 1). And the only thing I want to return in the query is filer_info.filer_ident and the count.
This gives me every row, but I only want the data where filer_ident > 1 in the returned rows.
select * from filer_info f
inner join filer_persent fp on f.filer_info_id=fp.filer_info_id
inner join persent_email p on fp.persent_info_id=p.persent_info_id
where fp.filer_persent_kind_cd = 'FILER' and p.persent_email_kind_cd='PRIMARY'
order by f.filer_ident

SELECT filer_ident, cnt
FROM (
SELECT filer_info_id, COUNT(*) cnt
FROM filer_persent fp
JOIN persent_email p
USING (persent_info_id)
WHERE (fp.filer_persent_kind_cd, p.persent_email_kind_cd) = ('FILER', 'PRIMARY')
HAVING COUNT(*) > 1
) с
JOIN filer_info f
USING (filer_info_id)
WHERE filer_ident > 1
ORDER BY
f.filer_ident

Related

Return only results that match more than 2 conditions

How do I only return results if more than two values from a list are found?
For example, if they don't have at least three of the following codes attached to their account then don't include them:
I13.0
I13.2
I20.0
I20.1
I20.8
I20.9
I21.01
I21.02
I21.09
I21.11
I21.19
I21.21
I21.29
I21.3
I21.4
I21.9
I21.A1
I21.A9
I22.0
Do I just need to put having count(distinct PROB.ICD10DiagnosisCode) > 2 after the group statement? I am getting results but I want to make sure I am not taking the long way around the bus.
SELECT DISTINCT
PER.ID AS PatientID,
IORG.OrganizationMRN AS PatientMRN
FROM works..Problem PROB (nolock)
JOIN works..Problem_Encounter PROBENC ON PROB.ID = PROBENC.ProblemID
JOIN works..Encounter ENC ON PROBENC.EncounterID = ENC.ID
JOIN works..patient_member PM ON ENC.PatientID = PM.ID
JOIN works..Document ON Document.EncounterID = ENC.ID
JOIN works..DocumentEvent
ON Document.documentid = DocumentEvent.documentid
JOIN works..Person PER ON Document.PatientID = PER.ID
JOIN works..Patient_Iorg IORG
ON PER.ID = IORG.PersonID and IORG.InternalOrganization = 3
WHERE PROB.ProblemStatusDE IN (9)
AND PROB.RecordedDTTM > DATEADD(month,-6,GETDATE())
AND PROB.ICD10DiagnosisCode IN
(
SELECT ICD10DiagnosisCode
FROM CVCReports.dbo.rptPETEligibleICD10
)
AND PM.IsDeceasedFLAG = 'N'
AND DocumentEvent.documenteventde NOT IN (18)
AND Document.Status LIKE 'Final%'
AND Document.DocumentTypeDE NOT IN (288)
AND ENC.DTTM > DATEADD(year,-2,GETDATE())
GROUP BY OrganizationMrn, PER.ID
having count(distinct PROB.ICD10DiagnosisCode) > 2

Get the sum of a count column in SQL

I have the following query
SELECT
dtc.coupon_type_company_name,
COUNT(*) * dtc.coupon_type_company_coupon_amount AS 'Total_Coupon_To_Be_Used',
dtc.coupon_type_company_coupon_months_combinable
FROM
[dbo].[coupon_type_Company_User] dtcu
JOIN
coupon_type_Company dtc ON dtcu.coupon_type_Company_ID = dtc.id
JOIN
person p ON dtcu.userID = p.userID
WHERE
coupon_type_company_coupon_is_combinable = 1
OR coupon_type_company_has_coupon = 1
AND dtc.companyID = 1081
AND p.is_active = 1
GROUP BY
dtc.coupon_type_company_name,dtc.coupon_type_company_coupon_amount,
dtc.coupon_type_company_coupon_months_combinable
This returns the following:
What I want to have however is just one column and one row that should take the SUM of my middle column (count(*)*dtc.coupon_type_company_coupon_amount).
How could I achieve this and prevent doing this in my code backend (C#)
You can wrap your query like this:
SELECT SUM(Total_Coupon_To_Be_Used) AS the_sum
FROM (
your query
) s
Use a "Table Expression", as in:
select sum(Total_Coupon_To_Be_Used) from (
SELECT dtc.coupon_type_company_name,
count(*) * dtc.coupon_type_company_coupon_amount as 'Total_Coupon_To_Be_Used',
dtc.coupon_type_company_coupon_months_combinable
FROM [dbo].[coupon_type_Company_User] dtcu
JOIN coupon_type_Company dtc ON dtcu.coupon_type_Company_ID = dtc.id
JOIN person p ON dtcu.userID = p.userID
WHERE coupon_type_company_coupon_is_combinable = 1
or coupon_type_company_has_coupon = 1
and dtc.companyID = 1081
AND p.is_active = 1
GROUP BY
dtc.coupon_type_company_name,dtc.coupon_type_company_coupon_amount,
dtc.coupon_type_company_coupon_months_combinable
) x

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.

where statement execute before inner join

I'm trying to grab the first instance of each result with a sysAddress of less than 4. However my statement currently grabs the min(actionTime) result first before applying the where sysAddress < 4. I'm trying to have the input for the inner join as the where sysAddress < 4 however i cant seem to figure out how to do it.
Should i be nesting it all differently? I didnt want to create an additional layer of table joins. Is this possible? I'm a bit lost at all the answers ive found.
SELECT
tblHistoryObject.info,
tblHistory.actionTime,
tblHistoryUser.userID,
tblHistoryUser.firstName,
tblHistoryUser.surname,
tblHistory.eventID,
tblHistoryObject.objectID,
tblHistorySystem.sysAddress
FROM tblHistoryObject
JOIN tblHistory
ON (tblHistory.historyObjectID = tblHistoryObject.historyObjectID)
JOIN tblHistorySystem
ON (tblHistory.historySystemID = tblHistorySystem.historySystemID)
JOIN tblHistoryUser
ON (tblHistory.historyUserID = tblHistoryUser.historyUserID)
INNER JOIN (SELECT
MIN(actionTime) AS recent_date,
historyObjectID
FROM tblHistory
GROUP BY historyObjectID) AS t2
ON t2.historyObjectID = tblHistoryObject.historyObjectID
AND tblHistory.actionTime = t2.recent_date
WHERE sysAddress < 4
ORDER BY actionTime ASC
WITH
all_action_times AS
(
SELECT
tblHistoryObject.info,
tblHistory.actionTime,
tblHistoryUser.userID,
tblHistoryUser.firstName,
tblHistoryUser.surname,
tblHistory.eventID,
tblHistoryObject.objectID,
tblHistorySystem.sysAddress,
ROW_NUMBER() OVER (PARTITION BY tblHistoryObject.historyObjectID
ORDER BY tblHistory.actionTime
)
AS historyObjectID_SeqByActionTime
FROM
tblHistoryObject
INNER JOIN
tblHistory
ON tblHistory.historyObjectID = tblHistoryObject.historyObjectID
INNER JOIN
tblHistorySystem
ON tblHistory.historySystemID = tblHistorySystem.historySystemID
INNER JOIN
tblHistoryUser
ON tblHistory.historyUserID = tblHistoryUser.historyUserID
WHERE
tblHistorySystem.sysAddress < 4
)
SELECT
*
FROM
all_action_times
WHERE
historyObjectID_SeqByActionTime = 1
ORDER BY
actionTime ASC
This does exactly what your original query did, without trying to filter by action_time.
Then it appends a new column, using ROW_NUMBER() to generate sequences from 1 for each individual tblHistoryObject.historyObjectID. Then it takes only the rows where this sequence value is 1 (the first row per historyObjectID, when sorted in action_time order).