Ways to stop SQL query from displaying a table multiple times? - sql

In my script, I have a table displaying the results of a SQL query. However, I am using the results as a summary, but the SQL is making the page display the table as many times as there are results (rows) in the returning SQL that are allowed because of the Where clause. I.e. if there were 3 groups of people summarized, the table repeats the same information 3 times
Are there any common ways to address this issue? Thanks!
SELECT
Demographics.Name,
Demographics.NDoc_Number,
Demographics.PID_alphanumeric,
Demographics.Company,
Demographics.Company_Name,
Demographics.Location,
Demographics.Location_Name,
Demographics.Team_CMT,
Demographics.Case_Manager,
Demographics.Case_Manager_UID,
Demographics.SiteName,
CareEpisodes.BGNDATE,
CareEpisodes.BRFA,
CareEpisodes.ENDDATE,
CareEpisodes.ERFA,
OASIS_Improvement.BGNRPT,
OASIS_Improvement.ENDRPT,
ISNULL(SUM(CASE OASIS_Improvement.O_I_#Request.MooNum~
WHEN 'NA'
THEN 1
ELSE 0
END),0) AS numberImproveNA,
ISNULL(SUM(CASE OASIS_Stabilization.O_S_#Request.MooNum~
WHEN 'NA'
THEN 1
ELSE 0
END),0) AS numberStabilizeNA,
ISNULL(SUM(CASE OASIS_Improvement.O_I_#Request.MooNum~
WHEN 'NA'
THEN 0
ELSE 1
END),0) AS couldShowImprovement,
ISNULL(SUM(CASE OASIS_Stabilization.O_S_#Request.MooNum~
WHEN 'NA'
THEN 0
ELSE 1
END),0) AS couldShowStabilization,
ISNULL(COUNT(Demographics.Name),0) AS patientCount,
ISNULL(SUM(CASE OASIS_Improvement.O_I_#Request.MooNum~
WHEN 1
THEN 1
ELSE 0
END),0) AS doShowImprovement,
ISNULL(SUM(CASE OASIS_Stabilization.O_S_#Request.MooNum~
WHEN 1
THEN 1
ELSE 0
END),0) AS doShowStabilization
FROM
Demographics
INNER JOIN OASIS_Improvement ON
Demographics.NDoc_Number = OASIS_Improvement.NDocNumber
INNER JOIN OASIS_Stabilization ON
Demographics.NDoc_Number = OASIS_Stabilization.NDocNumber AND
OASIS_Improvement.BGNRPT=OASIS_Stabilization.BGNRPT
INNER JOIN CareEpisodes ON
Demographics.NDoc_Number = CareEpisodes.NDocNumber AND
OASIS_Improvement.BGNRPT=CareEpisodes.BGNRPT
WHERE
(Demographics.Company IN (#SingleQuote.Request.companyInput~) OR '#Request.companyInput~' = '') AND
(Demographics.Location IN (#SingleQuote.Request.locationInput~) OR '#Request.locationInput~' = '') AND
(Demographics.Team_CMT IN (#SingleQuote.Request.teamInput~) OR '#Request.teamInput~' = '') AND
(Demographics.Case_Manager_UID IN (#SingleQuote.Request.clinicianInput~) OR '#Request.clinicianInput~' = '') AND
CareEpisodes.ERFA <> 6 AND
(OASIS_Improvement.O_I_#Request.MooNum~ = 'NA' OR
OASIS_Improvement.O_I_#Request.MooNum~ = 1 OR
OASIS_Improvement.O_I_#Request.MooNum~ = 0) AND
(OASIS_Stabilization.O_S_#Request.MooNum~ = 'NA' OR
OASIS_Stabilization.O_S_#Request.MooNum~ = 0 OR
OASIS_Stabilization.O_S_#Request.MooNum~ = 1) AND
CareEpisodes.BGNDATE >= '#Request.FromDateInput~' AND
CareEpisodes.ENDDATE <= '#Request.ThruDateInput~'

You need to think about using a GROUP BY statement if you are trying to group the information. If you want to summarize the information try looking at the GROUP BY but WITH ROLLUP. ROLLUP will allow you to group and summarize information depending on the values you select in your GROUP BY.

Related

SQL Server. dynamic query error while using aggregate function

I am little bit new to SQL. I am trying to run below shown dynamic query
SET #SQL ='
select Distinct count(*) TotalCount,
sum(case when ap.FormStatus = ''open'' then 1 else 0 end) AS Totalopenstatus,
sum(case when ap.FormStatus = ''Pending'' then 1 else 0 end) AS TotalPendingstatus,
sum(case when ap.FormStatus = ''Awaiting L1 Review'' then 1 else 0 end) AS TotalAssociates,
sum(case when ap.FormStatus = ''Awaiting L2 Review'' then 1 else 0 end) AS TotalL1reviews,
sum(case when ap.FormStatus = ''Awaiting Delivery Head'' then 1 else 0 end) AS TotalL2reviews
from [dbo].[Appraisals] ap
LEFT join [dbo].[FinalReviewClosures] fi ON ap.FinalReviewClosure_Id = fi.id
join [dbo].[employees] emp ON fi.Employee_Id = emp.id
where fi.FinancialYear ='+#FinancialYear +' AND ap.Quarter = '+#Quarter+' '
but I get this error:
Msg 245, Level 16, State 1, Procedure sp_GetReviewStatus, Line 51 [Batch Start Line 11]
Conversion failed when converting the nvarchar value
Code:
select Distinct count(*) TotalCount,
sum(case when ap.FormStatus = 'open' then 1 else 0 end) AS Totalopenstatus,
sum(case when ap.FormStatus = 'Pending' then 1 else 0 end) AS TotalPendingstatus,
sum(case when ap.FormStatus = 'Awaiting L1 Review' then 1 else 0 end) AS TotalAssociates,
sum(case when ap.FormStatus = 'Awaiting L2 Review' then 1 else 0 end) AS TotalL1reviews,
sum(case when ap.FormStatus = 'Awaiting Delivery Head' then 1 else 0 end) AS TotalL2reviews
from [dbo].[Appraisals] ap
LEFT join [dbo].[FinalReviewClosures] fi ON ap.FinalReviewClosure_Id = fi.id
join [dbo].[employees] emp ON fi.Employee_Id = emp.id
where fi.FinancialYear =2020-2021 AND ap.Quarter = Q3 AND emp.office = ' to data type int.
Please help me fix this problem.
The reason what you have is failing is as has been mentioned. You are injecting values instead of parametrising and these values are creating invalid syntax in your "dynamic" query. (Read on to see why I say "dynamic".)
fi.FinancialYear ='+#FinancialYear +' becomes fi.FinancialYear =2020-2021, which is effectively fi.FinancialYear = -1 (what year is -1?). This will cause an error if fi.FinancialYear isn't able to be converted implicitly to an int.
ap.Quarter = '+#Quarter becomes ap.Quarter = Q3 and unless you have a column called Q3 then you're going to get an invalid column error.
If you are using dynamic SQL then never inject unsanitised values; quote your object names using QUOTENAME and parametrise your parameters (which you can do with sys.sp_executesql).
What you have, however, has no need to be a "dynamic" query; there is nothing dynamic about it. Just use a non-dynamic parametrised query and the query will work fine:
SELECT --DISTINCT --Not needed, as the query will only return 1 row.
--Even if you did have a GROUP BY the DISTINCT isn't needed,
--as the GROUP BY will already put the data in DISTINCT sets.
COUNT(*) AS TotalCount,
SUM(CASE WHEN ap.FormStatus = 'open' THEN 1 ELSE 0 END) AS Totalopenstatus,
SUM(CASE WHEN ap.FormStatus = 'Pending' THEN 1 ELSE 0 END) AS TotalPendingstatus,
SUM(CASE WHEN ap.FormStatus = 'Awaiting L1 Review' THEN 1 ELSE 0 END) AS TotalAssociates,
SUM(CASE WHEN ap.FormStatus = 'Awaiting L2 Review' THEN 1 ELSE 0 END) AS TotalL1reviews,
SUM(CASE WHEN ap.FormStatus = 'Awaiting Delivery Head' THEN 1 ELSE 0 END) AS TotalL2reviews
FROM [dbo].[Appraisals] ap
LEFT JOIN [dbo].[FinalReviewClosures] fi ON ap.FinalReviewClosure_Id = fi.id
JOIN [dbo].[employees] emp ON fi.Employee_Id = emp.id
WHERE fi.FinancialYear = #FinancialYear --I assume fi.FinancialYear and #FinancialYear have the same data type?
AND ap.Quarter = #Quarter; --I assume ap.Quarter and #Quarter have the same data type?
Where clause should be
where fi.FinancialYear ='2020-2021' AND ap.Quarter = 'Q3' AND emp.office = ' to data type int.'
instead of
where fi.FinancialYear =2020-2021 AND ap.Quarter = Q3 AND emp.office = ' to data type int.
Please also let me know the data type of #financialYear and #Quarter

SQL Year over Year Performance with Criteria

I am trying to return year over year results based on date criteria. There is additional information I would like to include in the query i.e. first date of activity and first date of activity with spot name like '%6%'. The current query I have is multiplying the correct amounts by 6 and I can't figure out how to solve. When I remove the first "where" clause I get the correct amounts. Any help would be appreciated.
Select
V.IGB_License,
DBA,
V.Sci_Games_Name,
convert(date,v2.Activity_date) as First6thMachineDate,
convert(date,V3.Activity_date) as GoLiveDate,
sum(case when (v.Activity_date between '1/23/2019' and DATEADD(YEAR,-2,getdate()-1)) then v.Funds_in else 0 end) as FundsIn2019,
sum(case when (v.Activity_date between '1/23/2020' and DATEADD(YEAR,-1,getdate()-1)) then v.Funds_in else 0 end) as FundsIn2020,
sum(case when (v.Activity_date between '1/23/2021' and getdate()) then v.Funds_in else 0 end) as FundsIn2021,
sum(case when (v.Activity_date between '1/23/2019' and DATEADD(YEAR,-2,getdate()-1)) then v.Net_funds else 0 end) as NetFunds2019,
sum(case when (v.Activity_date between '1/23/2020' and DATEADD(YEAR,-1,getdate()-1)) then v.Net_funds else 0 end) as NetFunds2020,
sum(case when (v.Activity_date between '1/23/2021' and getdate()) then v.Net_funds else 0 end) as NetFunds2021
From VGT_activity V
Left Join Locations on v.IGB_License = Locations.IGB_License
left join VGT_activity V2 on v.IGB_License = v2.IGB_License
Left join VGT_activity V3 on v.IGB_License = v3.IGB_License
Where v2.Activity_date = (
Select Min(V1.Activity_date)
From VGT_activity V1
Where v1.IGB_License = V2.IGB_License
and Spot_name like '%6%'
)
and v3.Activity_date = (
Select Min(V1.Activity_date)
From VGT_activity V1
Where v1.IGB_License = V3.IGB_License
)
group by V.IGB_License, dba, V.Sci_Games_Name, v2.Activity_date, v3.Activity_date
order by 4

SQL Query to Combine rows

I have a query that currently prints out what I need but doesn't combine the rows that I need. For example, I need the first two rows with the meter name to be combined together and so on for the rest of the meter names.
This is currently what I have:
SELECT
--Displays Client Number
CASE
WHEN v.MID IS NULL THEN ''
ELSE v.ClientNumber
END AS 'Client Number',
--Displays MID Number
CASE
WHEN v.MID IS NULL THEN ''
ELSE v.MID
END AS MID,
--Displays Meter Name
CASE
WHEN v.MID IS NULL THEN ''
ELSE v.MeterName
END AS 'Meter Name',
/*
CASE
WHEN v.MID IS NULL THEN 0
ELSE SUM(v.MCF)
END AS MCF,
*/
--Displays January's MCF
CASE
WHEN v.AccountPeriod = '2018-01-01' THEN SUM(v.MCF)
ELSE 0
END AS January,
--Displays Febuary's MCF
CASE
WHEN v.AccountPeriod = '2018-02-01' THEN SUM(v.MCF)
ELSE 0
END AS Febuary,
CASE
WHEN v.MID IS NULL THEN 0
ELSE SUM(v.mcf)
END AS 'Meter Total'
FROM Volumes v
LEFT JOIN CurrentMeters cm
ON v.MID = cm.MID
WHERE cm.ClientNumber = 107500
GROUP BY v.MID, v.AccountPeriod, v.ClientNumber, v
Does anyone have any suggestions as to what I should do or how I should approach this?
I think you just want conditional aggregation:
SELECT (CASE WHEN v.MID IS NULL THEN '' ELSE v.ClientNumber END) AS Client_Number,
COALESCE(WHEN v.MID, '') as MID,
(CASE WHEN v.MID IS NULL THEN '' ELSE v.MeterName END) AS Meter_Name,
SUM((CASE WHEN v.MID IS NULL THEN 0 v.MCF END) AS MCF,
SUM(CASE WHEN v.AccountPeriod = '2018-01-01' THEN v.MCF ELSE 0 END) AS January,
SUM(CASE WHEN v.AccountPeriod = '2018-02-01' THEN v.MCF ELSE 0 END) AS January,
SUM(CASE WHEN v.MID IS NULL THEN 0 ELSE v.mcf END) AS Meter_Total
FROM Volumes v JOIN
CurrentMeters cm
ON v.MID = cm.MID
WHERE cm.ClientNumber = 107500
GROUP BY (CASE WHEN v.MID IS NULL THEN '' ELSE v.ClientNumber END),
COALESCE(WHEN v.MID, ''),
(CASE WHEN v.MID IS NULL THEN '' ELSE v.MeterName END);
Notes:
Your WHERE clause is turning the outer join into an inner join, so there is no reason to express an outer join.
The GROUP BY keys specify what defines a row in the result set. Each combination of unique values in the data is in exactly one row. Hence, you don't want AccountPeriod in the GROUP BY.
Presumably, you want one row for each of the expressions that define a row, so these expressions are in the group by.
For conditional aggregation, the CASE expression is an argument to an aggregation function such as SUM().

Update a complex SQL query to add a new column with the sum of two columns

The below SQL query creates a table with n number of columns named in the next line.
...., curr_amount, tax_amount, ....
I am having a very tough time updating the below query to create a new column called total and position it exactly after tax_amount column and the total column should contain the values that are obtained after sum of curr_amount & tax_amount.
I have been working on this from more than one day but couldn't figure it out.
P.S. Still a noob here. Thanks alot for your time.
.
SELECT Isnull(t.total_month, 'Total') total_month,
t.tax_amount,
t.curr_amount,
t.usage_qty,
t.kh_qty,
t.bill_cnt
FROM (SELECT dbo.Sigmadf(bm.posted_date, 'YYYY-MM') total_month,
Sum(CASE
WHEN rr.usage_qty IS NULL THEN 0
ELSE Cast (rr.usage_qty AS NUMERIC(18, 2))
END) usage_qty,
Sum(CASE
WHEN bm.curr_amount IS NULL THEN 0
ELSE bm.curr_amount
END) curr_amount,
Sum(CASE
WHEN bm.adj_amount IS NULL THEN 0
ELSE bm.adj_amount
END) adj_amount,
Sum(CASE
WHEN bm.bal_fwd_amount IS NULL THEN 0
ELSE bm.bal_fwd_amount
END) bal_forward,
Sum(CASE
WHEN bm.tax_amount IS NULL THEN 0
ELSE bm.tax_amount
END) tax_amount,
Sum(CASE
WHEN bm.due_amount IS NULL THEN 0
ELSE bm.due_amount
END) due_amount,
Sum(CASE
WHEN bm.last_total_paid_amount IS NULL THEN 0
ELSE bm.last_total_paid_amount * -1
END) paid_amount,
Sum(CASE
WHEN bm.bill_print = 'Y' THEN 1
ELSE 0
END) pdf_cnt,
Sum(CASE
WHEN Isnull(bm.bill_handling_code, '0') = '0' THEN 1
ELSE 0
END) reg_cnt,
Sum(CASE
WHEN Isnull(bm.bill_handling_code, '0') = '1' THEN 1
ELSE 0
END) ftime_cnt,
Sum(CASE
WHEN Isnull(bm.bill_handling_code, '0') = '9999' THEN 1
ELSE 0
END) ltime_cnt,
Count(*) bill_cnt,
Sum(CASE
WHEN bill_status = '01' THEN 1
ELSE 0
END) canc_cnt,
Sum(CASE
WHEN bill_status = '01' THEN
CASE
WHEN rr.usage_qty IS NULL THEN 0
ELSE Cast (rr.usage_qty AS NUMERIC(18, 2))
END
ELSE 0
END) canc_usg,
Sum(CASE
WHEN vis.kh_qty IS NULL THEN 0
ELSE Cast(vis.kh_qty AS NUMERIC(18, 2))
END) kh_qty
FROM bill_master bm WITH (nolock)
INNER JOIN (SELECT bill_no,
Sum(CASE
WHEN vpb.recurr_charge_type IN ( 'T4',
'SLF' )
THEN
CASE
WHEN vpb.print_qty = 'Y'
AND vpb.usage_qty IS NOT NULL
THEN
Cast (vpb.usage_qty AS
NUMERIC(18, 2))
ELSE 0
END
ELSE 0
END) usage_qty
FROM v_print_bills_all vpb
GROUP BY bill_no) rr
ON rr.bill_no = bm.bill_no
LEFT OUTER JOIN vis_bill_master_cr vis WITH (nolock)
ON bm.bill_no = vis.bill_no
WHERE 1 = 1
AND dbo.Trunc(bm.posted_date) >= '20150101'
AND dbo.Trunc(bm.posted_date) <= '20151124'
AND bm.posted_date IS NOT NULL
AND bm.cust_id NOT IN (SELECT cc.code_type cust_id
FROM code_table cc WITH (nolock)
WHERE cc.code_tabname = 'RptExclCust'
AND cc.code_value = 'cust_id')
GROUP BY dbo.Sigmadf(bm.posted_date, 'YYYY-MM') WITH rollup)t
I must say that the explanation is not so clear.
From my understanding, you want the total of two columns.
So, wrap all your query between parenthesis, call it subQuery, and make the sum of the two columns on top:
SELECT subQuery.total_month as bill_date,
subQuery.curr_amount as amount,
subQuery.tax_amount tax,
subQuery.curr_amount + subQuery.tax_amount as [total],
...
FROM
(..your entire query here..) as subQuery

Trying to group several rows based on donatedmoney status

I'm really struggling with this. I just can't seem to figure it out. I've got the concept in my head but don't exactly know how to put my plain language understanding of how to solve the problem into the correct Syntax.
Here is the question.
Give me a list of all donors and their addresses categorized by whether they donated art, money, or both.
Here is the set up for the tables.
CareTakers: CareTakerID, CareTakerName
Donations: DonationID, DonorID, DonatedMoney, ArtName, ArtType, ArtAppraisedPrice, ArtLocationBuilding, ArtLocationRoom, CareTakerID
Donors: DonorID, DonorName, DonorAddress
Here is what I have for my code so far.
SELECT
DISTINCT(DonorName), DonorAddress
FROM
Donors JOIN Donations ON Donors.DonorID = Donations.DonorID
GROUP BY
DonatedMoney
HAVING
DonatedMoney = 'Y' OR DonatedMoney = 'N' OR DonatedMoney = 'Y' AND ArtName IS NOT NULL
Any help would be highly appreciated!
Why would you use a having clause? The question specifies no filtering. The following summarizes the donations to get what you need and then joins the results back to the donors table:
select d.*, don.DonationType
from donors d join
(select don.donorid,
(case when sum(case when donatedmoney = 'Y' then 1 else 0 end) > 0 and
sum(case when artname is not null then 1 else 0 end) > 0
then 'Both'
when sum(case when donatedmoney = 'Y' then 1 else 0 end) > 0
then 'Money'
when sum(case when artname is not null then 1 else 0 end)
then 'Art'
else 'Neither'
end) as DonationType
from donations don
group by don.donorid
) don
on d.donorid = don.donorid