How to use Count and Sum in the Same Query? - sql-server

I have written the following query using the Aggregate function "SUM".
SELECT
D.PODetailID,
SUM(D.AcceptedQty)
FROM STR_MRVDetail D
INNER JOIN STR_MRVHeader H ON H.MRVID = D.MRVID
INNER JOIN PUR_POHeader PH ON PH.POID = H.POID
INNER JOIN PUR_PODetail PD ON PD.PODetailID = D.PODetailID
WHERE H.StatusID = 4
AND PH.POID = 839
AND (SELECT
SUM(AcceptedQty)
FROM
STR_MRVDetail
WHERE
STR_MRVDetail.PODetailID = PD.PODetailID) =
(SELECT POQuantity FROM PUR_PODetail
WHERE PUR_PODetail.PODetailID = PD.PODetailID)
GROUP BY D.PODetailID
Currently this Query returns 2 rows. I want to retrieve the count of this query. How to count the rows of the above query?

You can add ##ROWCOUNT to the query, which also gives you the final result set as well as the count of all the rows in the result set.
SELECT D.PODetailID, SUM(D.AcceptedQty), ##ROWCOUNT FROM STR_MRVDetail D
INNER JOIN STR_MRVHeader H ON H.MRVID = D.MRVID
INNER JOIN PUR_POHeader PH ON PH.POID = H.POID
INNER JOIN PUR_PODetail PD ON PD.PODetailID = D.PODetailID
WHERE H.StatusID = 4
AND PH.POID = 839
AND (SELECT SUM(AcceptedQty) FROM STR_MRVDetail
WHERE STR_MRVDetail.PODetailID = PD.PODetailID) =
(SELECT POQuantity FROM PUR_PODetail
WHERE PUR_PODetail.PODetailID = PD.PODetailID)
GROUP BY D.PODetailID

SELECT COUNT(*) as Total_Rows
FROM
(
SELECT D.PODetailID as PODetailID, SUM(D.AcceptedQty) as Total_AcceptedQty
FROM STR_MRVDetail D
INNER JOIN STR_MRVHeader H ON H.MRVID = D.MRVID
INNER JOIN PUR_POHeader PH ON PH.POID = H.POID
INNER JOIN PUR_PODetail PD ON PD.PODetailID = D.PODetailID
WHERE H.StatusID = 4
AND PH.POID = 839
AND (SELECT SUM(AcceptedQty) FROM STR_MRVDetail
WHERE STR_MRVDetail.PODetailID = PD.PODetailID) =
(SELECT POQuantity FROM PUR_PODetail
WHERE PUR_PODetail.PODetailID = PD.PODetailID)
GROUP BY D.PODetailID
) as t

Related

performance significantly reduced when inner join table and views

I have three views in my sql server:
CREATE VIEW [dbo].[v_CompanyLabelCreate]
AS
SELECT
c.Id AS Id,
c.[Name] AS CompanyName,
CASE WHEN r.ApprovedPatentCreativeApplication > 2 OR r.ApprovedCopyRightBookApplication + r.ApprovedCopyRightSoftwareApplication > 4 OR NumberInProduction + NumberNotInProduction > 10 THEN N'创造型'
ELSE NULL END AS Label
FROM Company c INNER JOIN ResearchInfo r ON c.Id = r.CompanyID
WHERE c.Submitted = 1
CREATE VIEW [dbo].[v_CompanyLabelHighPotential]
AS
SELECT
c.Id AS Id,
c.[Name] AS CompanyName,
CASE WHEN si1.Income >= 1000000 AND si2.Income <> 0 AND ((si1.Income -si2.Income)/si2.Income) >= 1 THEN N'潜力型'
WHEN n1.TotalProfit >= 500000 AND n2.TotalProfit <> 0 AND ((n1.TotalProfit - n2.TotalProfit)/n2.TotalProfit) >= 1 THEN N'潜力型'
WHEN nfa1.AssetsTotal >= 5000000 AND nfa2.AssetsTotal <> 0 AND ((nfa1.AssetsTotal - nfa2.AssetsTotal)/nfa2.AssetsTotal) >= 1 THEN N'潜力型'
ELSE NULL END AS Label
FROM Company c INNER JOIN SaleIncome si1 ON c.Id = si1.CompanyID AND si1.YearQuarterID = 2
INNER JOIN SaleIncome si2 ON c.Id = si2.CompanyID AND si2.YearQuarterID = 1
INNER JOIN NetProfit n1 ON c.Id = n1.CompanyID AND n1.YearQuarterID = 2
INNER JOIN NetProfit n2 ON c.Id = n2.CompanyID AND n2.YearQuarterID = 1
INNER JOIN NonFloatingAsset nfa1 ON c.Id = nfa1.CompanyID AND nfa1.YearQuarterID = 2
INNER JOIN NonFloatingAsset nfa2 ON c.Id = nfa2.CompanyID AND nfa2.YearQuarterID = 1
WHERE c.Submitted = 1
CREATE VIEW [dbo].[v_CompanyLabelHighTotalPolicies]
AS
SELECT
c.Id AS Id,
c.[Name] AS CompanyName,
CASE WHEN p.NumberOfPolicies >= 4 AND cp.PolicyID IS NOT NULL THEN N'政策大户'
ELSE NULL END AS Label
FROM Company c LEFT JOIN (SELECT CompanyID, COUNT(*) AS NumberOfPolicies FROM CompanyPolicy GROUP BY CompanyID) p ON c.Id = p.CompanyID
LEFT JOIN (SELECT CompanyID, PolicyID FROM CompanyPolicy WHERE PolicyID = 7) cp ON c.Id = cp.CompanyID
WHERE c.Submitted = 1
When I run a select query which inner joins these three views:
select *
from v_CompanyLabelCreate clc
INNER JOIN v_CompanyLabelHighPotential clhp ON clc.Id = clhp.Id
INNER JOIN v_CompanyLabelHighTotalPolicies chtp ON clc.Id = chtp.Id
It is fast and smooth. However, when I try to run a select query which inner join these three views with some other tables:
select *
FROM Company c
INNER JOIN BasicInfo b ON c.Id = b.CompanyID
INNER JOIN CompanyDimension cd ON c.Id = cd.CompanyID
INNER JOIN TotalProfit t ON c.Id = t.CompanyID AND t.YearQuarterID = 2
INNER JOIN SaleCost sc ON c.Id = sc.CompanyID AND sc.YearQuarterID = 2
INNER JOIN CompanyFinancialIndex cfi ON c.Id = cfi.CompanyID AND cfi.YearQuarterID = 6
INNER JOIN SaleIncome si1 ON c.Id = si1.CompanyID AND si1.YearQuarterID = 2
INNER JOIN SaleIncome si2 ON c.Id = si2.CompanyID AND si2.YearQuarterID = 1
INNER JOIN NetProfit n1 ON c.Id = n1.CompanyID AND n1.YearQuarterID = 2
INNER JOIN NetProfit n2 ON c.Id = n2.CompanyID AND n2.YearQuarterID = 1
INNER JOIN v_CompanyLabelCreate clc ON c.Id = clc.Id
INNER JOIN v_CompanyLabelHighPotential clhp ON clc.Id = clhp.Id
INNER JOIN v_CompanyLabelHighTotalPolicies chtp ON clc.Id = chtp.Id
WHERE c.Submitted = 1
It looks like it will take forever to get the result (Download the execution plan here: the execution plan). Now, if I just run the query without inner joining the three views like this:
select *
FROM Company c
INNER JOIN BasicInfo b ON c.Id = b.CompanyID
INNER JOIN CompanyDimension cd ON c.Id = cd.CompanyID
INNER JOIN TotalProfit t ON c.Id = t.CompanyID AND t.YearQuarterID = 2
INNER JOIN SaleCost sc ON c.Id = sc.CompanyID AND sc.YearQuarterID = 2
INNER JOIN CompanyFinancialIndex cfi ON c.Id = cfi.CompanyID AND cfi.YearQuarterID = 6
INNER JOIN SaleIncome si1 ON c.Id = si1.CompanyID AND si1.YearQuarterID = 2
INNER JOIN SaleIncome si2 ON c.Id = si2.CompanyID AND si2.YearQuarterID = 1
INNER JOIN NetProfit n1 ON c.Id = n1.CompanyID AND n1.YearQuarterID = 2
INNER JOIN NetProfit n2 ON c.Id = n2.CompanyID AND n2.YearQuarterID = 1
WHERE c.Submitted = 1
It is fast and smooth again.
About the tables used:
Company: A table which stores company Ids and company names. Of course c.Id is the PK and it will be referred to as Company ID later.
ResearchInfo, BasicInfo, CompanyDimension, CompanyFinancialIndex: CompanyID is foreign key, every company only has at most one row in this table.
SaleIncome, SaleCost, NetProfit, NonFloatingAsset, TotalProfit: the combination of CompanyID and YearQuarterID work as Primary Key, although every table has an identity field which is defined as the PK.
You also can have a missed index issue, but your query is a bit complex. You can try to reduce the complexity using cte table like (You need the field names be unique in CTEs):
WITH cte_tb1
AS (SELECT * -- UNIQUE NAMES FIELDS IS REQUIRED
FROM company c
INNER JOIN basicinfo b
ON c.id = b.companyid
INNER JOIN companydimension cd
ON c.id = cd.companyid
INNER JOIN totalprofit t
ON c.id = t.companyid
AND t.yearquarterid = 2
INNER JOIN salecost sc
ON c.id = sc.companyid
AND sc.yearquarterid = 2
INNER JOIN companyfinancialindex cfi
ON c.id = cfi.companyid
AND cfi.yearquarterid = 6
INNER JOIN saleincome si1
ON c.id = si1.companyid
AND si1.yearquarterid = 2
INNER JOIN saleincome si2
ON c.id = si2.companyid
AND si2.yearquarterid = 1
INNER JOIN netprofit n1
ON c.id = n1.companyid
AND n1.yearquarterid = 2
INNER JOIN netprofit n2
ON c.id = n2.companyid
AND n2.yearquarterid = 1
WHERE c.submitted = 1),
cte_tb2
AS (SELECT * -- UNIQUE NAMES FIELDS IS REQUIRED
FROM v_companylabelcreate clc
INNER JOIN v_companylabelhighpotential clhp
ON clc.id = clhp.id
INNER JOIN v_companylabelhightotalpolicies chtp
ON clc.id = chtp.id)
SELECT *
FROM cte_tb1 a
INNER JOIN cte_tb2 b
ON a.id = b.id

Count item corresponding listed Item

SELECT a.UPC,COUNT(*)
FROM StoreTransactions a WITH (NOLOCK)
JOIN StoreTransactions_Expanded_UOM c
ON a.StoreTransactionID = c.StoreTransactionID
LEFT JOIN ProductCatalog cat
ON a.ProductID = cat.ProductID
LEFT JOIN ProductCatalogBase base
ON cat.ProductCatalogID = base.ProductCatalogID
JOIN ProductIdentifiers d
ON cat.ProductID = d.ProductID AND d.ProductIdentifierTypeID = 2
GROUP BY a.UPC
, d.IdentifierValue, cat.PackDesc, a.ReportedCost,
base.ManualHigh, base.ManualLow,cat.DateTimeCreated,cat.DateTimeLastUpdate
ORDER BY count(*) desc
I want count of UPC corresponding UPC but not getting correct result like below.
UPC Count
071990316006 1463
026565245455 4530
You only need to group by a.UPC:
SELECT a.UPC,COUNT(*)
FROM StoreTransactions a WITH (NOLOCK)
JOIN StoreTransactions_Expanded_UOM c
ON a.StoreTransactionID = c.StoreTransactionID
LEFT JOIN ProductCatalog cat
ON a.ProductID = cat.ProductID
LEFT JOIN ProductCatalogBase base
ON cat.ProductCatalogID = base.ProductCatalogID
JOIN ProductIdentifiers d
ON cat.ProductID = d.ProductID AND d.ProductIdentifierTypeID = 2
GROUP BY a.UPC
ORDER BY count(*) desc

How to group row value using SQL Server?

I want to group same yAxisTitle in SQL Server, below image shows my data.
Expected result:
Query I used:
select
q.questionId, q.questionName,
p.perspectiveTitle, x.xAxisTitle, y.yAxisTitle, c.value
from
coaching_questionPerspectiveMap as c
inner join
Coaching_question as q on c.questionId = q.questionId
inner join
Coaching_perspective as p on c.perspectiveId = p.perspectiveId
inner join
coaching_xAxisData x on c.xAxisDataId = x.xAxisDataId
inner join
coaching_yAxisData y on c.yAxisDataId = y.yAxisDataId
where
q.questionId = 14
and p.perspectiveId = 1
order by
c.sort
Please provide any solution?
Thanks,
If you just want the data ordered so that it shows in groups of yAxisTitle, use this:
select
q.questionId, q.questionName,
p.perspectiveTitle, x.xAxisTitle, y.yAxisTitle, c.value
from
coaching_questionPerspectiveMap as c
inner join
Coaching_question as q on c.questionId = q.questionId
inner join
Coaching_perspective as p on c.perspectiveId = p.perspectiveId
inner join
coaching_xAxisData x on c.xAxisDataId = x.xAxisDataId
inner join
coaching_yAxisData y on c.yAxisDataId = y.yAxisDataId
where
q.questionId = 14
and p.perspectiveId = 1
order by
y.yAxisTitle, c.sort

How to return latest record from SQL Server

I have this query:
SELECT
t_ticket.ticketID, t_ticket.addedDate, t_ticket.question,
t_ticket.code, t_ticket.priority, t_orgSection.title,
t_actionTicket.addedDateAction, t_actionTicket.title AS Expr1
FROM
t_actionTicket
INNER JOIN
t_ticket ON t_actionTicket.ticketID_FK = t_ticket.ticketID
INNER JOIN
t_orgSection ON t_ticket.orgSectionID_FK = t_orgSection.orgSectionID
WHERE
(t_ticket.userID_FK = #userid) AND (t_ticket.cusDelete = 0)
I want to return just the latest record in t_actionTicket table for each row in t_ticket table.
You can use row_number to pick just the top row for each ticket ID, by ordering by your date and then making row = 1 one of your join criteria. See as follows:
Replace
FROM t_actionTicket INNER JOIN
t_ticket ON t_actionTicket.ticketID_FK = t_ticket.ticketID
with
FROM
(select *
, row_number() over (partition by ticketID_FK order by TicketActionDate desc) as RN
from t_actionTicket ) at
INNER JOIN t_ticket
ON at.ticketID_FK = t_ticket.ticketID and at.RN = 1
I guessed at the name of your date column in ActionTicket, so you will probably need to change that.
You can try this one too, just alternative:
SELECT t_ticket.ticketID, t_ticket.addedDate, t_ticket.question,t_ticket.code, t_ticket.priority, t_orgSection.title,t_actionTicket.addedDateAction, t_actionTicket.title AS Expr1
FROM t_ticket INNER JOIN
(select TOP 1 t_actionTicket.* from t_actionTicket INNER JOIN
t_ticket on t_ticket.ticketID = t_actionTicket.ticketID_FK ORDER BY
t_actionTicket.addedDateAction DESC ) AS t_actionTicket
ON t_actionTicket.ticketID_FK = t_ticket.ticketID
INNER JOIN t_orgSection ON t_ticket.orgSectionID_FK = t_orgSection.orgSectionID
WHERE (t_ticket.userID_FK = #userid) AND (t_ticket.cusDelete = 0)
I assume that addedDateAction uses timestamp when new record is inserted.
I find this solution
SELECT t_ticket.ticketID, t_ticket.addedDate, t_ticket.question,
t_ticket.code, t_ticket.priority, t_actionTicket.addedDateAction,
t_actionTicket.title AS Expr1
FROM t_actionTicket INNER JOIN t_ticket ON
t_actionTicket.ticketID_FK = t_ticket.ticketID INNER JOIN
(SELECT ticketID_FK, MAX(addedDateAction) AS maxDate
FROM t_actionTicket AS t_actionTicket_1
GROUP BY ticketID_FK) AS b ON t_actionTicket.ticketID_FK = b.ticketID_FK AND t_actionTicket.addedDateAction = b.maxDate
WHERE (t_ticket.userID_FK = #userid) AND (t_ticket.cusDelete = 0)

SQL Server AVG and Excel AVERAGE producing different results?

I'm trying to show averages on SQL server, but when I test the data in Excel the results are not the same, there must be something obvious I am missing.
Here is the code and results from SQL server:
SELECT DISTINCT
d.d_reference + ' - ' + d.d_name AS Faculty,
AVG(sub.GroupSize) AS FacultyAverage
FROM
unitesnapshot.dbo.capd_register r
INNER JOIN unitesnapshot.dbo.capd_studentregister sr ON sr.sr_register = r.r_id
INNER JOIN unitesnapshot.dbo.capd_activity a ON a.a_register = r.r_id
INNER JOIN unitesnapshot.dbo.capd_moduleactivity ma ON ma.ma_activity = a.a_id
INNER JOIN unitesnapshot.dbo.capd_module m ON m.m_id = ma.ma_activitymodule
INNER JOIN unitesnapshot.dbo.capd_department d ON d.d_id = m.m_moduledept
INNER JOIN unitesnapshot.dbo.capd_section sec ON sec.s_id = m.m_modulesection
INNER JOIN (SELECT
r.r_reference,
COUNT(DISTINCT s.s_studentreference) AS GroupSize
FROM
unitesnapshot.dbo.capd_student s
INNER JOIN unitesnapshot.dbo.capd_person p ON p.p_id = s.s_id
INNER JOIN unitesnapshot.dbo.capd_studentregister sr ON sr.sr_student = p.p_id
INNER JOIN unitesnapshot.dbo.capd_register r ON r.r_id = sr.sr_register
GROUP BY
r.r_reference) sub ON sub.r_reference = r.r_reference
WHERE
SUBSTRING(r.r_reference,4,2) = '12' AND
d.d_reference = '730'
GROUP BY
d.d_reference,
d.d_name
Here is the results in Excel:
Thanks
Try this for fun:
select avg(a)
from
(values(1),(2),(3),(4)) x(a);
avg(a)
-------
2
AVG() returns the same datatype as the base column. If your columns are of type int, then the result will be truncated to an int as well. The below returns the "correct" result.
select avg(cast(a as decimal(10,5)))
from
(values(1),(2),(3),(4)) x(a);
result
--------
2.5
The discrepancy you are showing (24 vs 19.50484) will most likely involve another error in conjunction with this. For example, to check that you are summing up the same data in Excel as in SQL Server, dump this result into Excel and sum it up. If it doesn't match what you currently believe is the Excel equivalent of the SQL Server data, line the columns up and check they have the same number of rows. Then sort each column individually by value ASCENDING and compare again.
SELECT d.d_name, sub.GroupSize AS FacultyAverage
FROM unitesnapshot.dbo.capd_register r
INNER JOIN unitesnapshot.dbo.capd_studentregister sr ON sr.sr_register = r.r_id
INNER JOIN unitesnapshot.dbo.capd_activity a ON a.a_register = r.r_id
INNER JOIN unitesnapshot.dbo.capd_moduleactivity ma ON ma.ma_activity = a.a_id
INNER JOIN unitesnapshot.dbo.capd_module m ON m.m_id = ma.ma_activitymodule
INNER JOIN unitesnapshot.dbo.capd_department d ON d.d_id = m.m_moduledept
INNER JOIN unitesnapshot.dbo.capd_section sec ON sec.s_id = m.m_modulesection
INNER JOIN (SELECT r.r_reference,
COUNT(DISTINCT s.s_studentreference) AS GroupSize
FROM unitesnapshot.dbo.capd_student s
INNER JOIN unitesnapshot.dbo.capd_person p ON p.p_id = s.s_id
INNER JOIN unitesnapshot.dbo.capd_studentregister sr ON sr.sr_student = p.p_id
INNER JOIN unitesnapshot.dbo.capd_register r ON r.r_id = sr.sr_register
GROUP BY r.r_reference) sub ON sub.r_reference = r.r_reference
WHERE SUBSTRING(r.r_reference,4,2) = '12' AND d.d_reference = '730'
ORDER BY d.d_name

Resources