i have a problem with sql execution time with Order By.
The problem is if i am doing Order By, it is take a long time and i have a peak on my server.
If there any way to take a max values without order by
Example of Code with Order By:
SELECT DISTINCT TOP 3 s.title, s.imageUrl, count(sv.saleid) as mostViewPeriod14Days, s.guid
FROM dbo.Sales s
INNER JOIN dbo.KEY_BrandcategoryToSale b_key ON s.id = b_key.saleId
INNER JOIN dbo.SaleView sv ON s.id = sv.saleId
WHERE (sv.date <= GETDATE())
AND (sv.date >= GETDATE() - 14)
AND s.isActive = 1 AND s.isHotsale = 1
AND b_key.brandCategoryId = 28 AND s.id NOT IN (SELECT sv.saleId FROM dbo.SaleView sv WHERE sv.userId = 99114)
GROUP BY s.title, s.imageUrl, s.guid
ORDER BY mostViewPeriod14Days Desc
And what i what is work good but without order:
SELECT DISTINCT TOP 3 s.title, s.imageUrl, count(sv.saleid) as mostViewPeriod14Days, s.guid
FROM dbo.Sales s
INNER JOIN dbo.KEY_BrandcategoryToSale b_key ON s.id = b_key.saleId
INNER JOIN dbo.SaleView sv ON s.id = sv.saleId
WHERE (sv.date <= GETDATE())
AND (sv.date >= GETDATE() - 14)
AND s.isActive = 1 AND s.isHotsale = 1
AND b_key.brandCategoryId = 28 AND s.id NOT IN (SELECT sv.saleId FROM dbo.SaleView sv WHERE sv.userId = 99114)
GROUP BY s.title, s.imageUrl, s.guid
Try the query below and let me know if it helps. A few general points below
WHERE clauses that contain a calculated date are slower than those that don't.
If you can avoid it, never put a "sub-select" in a query. Change that to a left join and check for null records (it's way faster)
DECLARE #Today DATETIME;
DECLARE #TwoWeeksAgo DATETIME;
SET #Today = GETDATE();
SET #TwoWeeksAgo = DATEADD(DAY, -14, GETDATE());
SELECT TOP 3
s.title,
s.imageUrl,
count(sv.saleid) as mostViewPeriod14Days,
s.guid
FROM dbo.Sales s
INNER JOIN dbo.KEY_BrandcategoryToSale b_key ON s.id = b_key.saleId
INNER JOIN dbo.SaleView sv ON s.id = sv.saleId
LEFT JOIN dbo.SaleView sv2 on sv2.id = sv.id and sv2.userId = 99114
WHERE sv.Date BETWEEN #TwoWeeksAgo AND #Today
AND sv2.id IS NULL -- This is the check that handles your sub-select earlier
AND s.isActive = 1 AND s.isHotsale = 1
AND b_key.brandCategoryId = 28
GROUP BY s.title, s.imageUrl, s.guid
ORDER BY mostViewPeriod14Days Desc
Related
Is there a way to multiply an aggregate function? I need to multiply SUM(ma.gewight) for every article (an article is, for example, H114972 which is iron and is 32,1 meters) so the GROUP BY groups all same articles and for every different article I need to multiply a different number (the column that I am using to multiply is e.best_wert which is the meters, mentioned above). So basically I need to multiply the SUM(ma.gewicht) with e.best_wert - but it doesn't work.
PS. Gewicht = weight
PSS. e.best_wert = weight value/meters
SELECT m.artikel, COUNT(ei.bestell_po) bestell_po_menge, SUM(ma.gewicht) AS summe_gewicht--, SUM(e.best_wert*ma.gewicht) AS summe_kg
FROM MATV030 m
INNER JOIN EINV030 e ON e.BESTELL_NR = m.BESTELL_NR
INNER JOIN EINV035 ei ON e.bestell_nr = ei.bestell_nr
INNER JOIN MATV010 ma ON m.ARTIKEL = ma.ARTIKEL
WHERE e.lieferant = '6000176' AND m.menge_buch <> 0
--AND m.artikel = 'H114972'
AND m.bs = 'WE' AND m.budatum >= '20190101' AND m.budatum < '20190201'
GROUP BY m.artikel, ma.gewicht
ORDER BY m.artikel ASC
Try like this
SELECT m.artikel, COUNT(ei.bestell_po) bestell_po_menge, SUM(ma.gewicht) AS summe_gewicht, (e.best_wert * SUM(ma.gewicht)) AS summe_kg
FROM MATV030 m
INNER JOIN EINV030 e ON e.BESTELL_NR = m.BESTELL_NR
INNER JOIN EINV035 ei ON e.bestell_nr = ei.bestell_nr
INNER JOIN MATV010 ma ON m.ARTIKEL = ma.ARTIKEL
WHERE e.lieferant = '6000176' AND m.menge_buch <> 0
--AND m.artikel = 'H114972'
AND m.bs = 'WE' AND m.budatum >= '20190101' AND m.budatum < '20190201'
GROUP BY m.artikel, e.best_wert
ORDER BY m.artikel ASC
Try this,
;With CTE as
(
SELECT ma.ARTIKEL, SUM(ma.gewicht) AS summe_gewicht--, SUM(e.best_wert*ma.gewicht) AS summe_kg
FROM MATV030 m
INNER JOIN MATV010 ma ON m.ARTIKEL = ma.ARTIKEL
WHERE m.menge_buch > 0
--AND m.artikel = 'H114972'
AND m.bs = 'WE' AND m.budatum >= '20190101' AND m.budatum < '20190201'
GROUP BY m.ARTIKEL
--ORDER BY m.artikel ASC
)
SELECT m.artikel, COUNT(ei.bestell_po) bestell_po_menge,summe_gewicht, summe_gewicht*e.best_wert AS summe_kg
FROM CTE C
inner join MATV030 m on m.artikel=c.artikel
INNER JOIN EINV030 e ON e.BESTELL_NR = m.BESTELL_NR
INNER JOIN EINV035 ei ON e.bestell_nr = ei.bestell_nr
WHERE e.lieferant = '6000176'
GROUP BY m.artikel
ORDER BY m.artikel ASC
You can create A CTE (Common Table Expression) table with your aggregate values and then multiply both the tables using CTE.
I am writing a query which is accepting a comma separated string and calculating the sum of transaction. which is working fine as result wise but taking too much time to execute in first attempt. I understand its need tuning but didn't find out the exact reason can any one point me whats wrong with my query.
Declare #IDs nvarchar(max)='1,4,5,6,8,9,43,183'
SELECT isnull(isnull(SUM(FT.PaidAmt),0) - isnull(SUM(CT.PaidAmt),0),0) [Amount], convert(char(10),FT.TranDate,126) [Date]
from FeeTransaction FT
Inner Join (
Select max(P.Id) [Id], P.TranMainId, isnull(SUM(P.AmtToPay),0) [Amt]
From Patient_Account P
Group By P.TranMainId
) PA ON FT.Id = PA.TranMainId
Inner Join Patient_Account XP ON PA.Id = XP.Id
Inner Join Master_Fee MF ON XP.FeeId = MF.Id
INNER Join Master_Patient MP ON FT.PID = MP.Id
Inner Join Master_FeeType TY ON MF.FeeTypeId = TY.Id
Left JOIN FeeTransaction CT on FT.TransactionId = CT.TransactionId AND CT.TranDate between '2019'+'08'+'01' and '2019'+'08'+'31' and CT.[Status] <> 'A' AND isnull(CT.IsCancel,0) = 1
Where convert(nvarchar,FT.TranDate,112) between '2019'+'08'+'01' and '2019'+'08'+'31' AND FT.[Status] = 'A' AND XP.FeeId in (SELECT val FROM dbo.f_split(#IDs, ','))
AND isnull(FT.IsCancel,0) = 0 AND FT.EntryBy = 'rajan'
Group By convert(char(10),FT.TranDate,126)
I would rephrase the query a bit:
select coalesce(SUM(FT.PaidAmt), 0) - coalesce(SUM(CT.PaidAmt), 0)as [Amount],
convert(char(10),FT.TranDate,126) [Date]
from FeeTransaction FT join
(select xp.*,
coalesce(sum(p.amttopay) over (TranMainId), 0) as amt
from Patient_Account XP ON PA.Id = XP.Id
) xp join
Master_Fee MF
on XP.FeeId = MF.Id join
Master_Patient MP
on FT.PID = MP.Id join
Master_FeeType TY
on MF.FeeTypeId = TY.Id left join
FeeTransaction CT
on FT.TransactionId = CT.TransactionId and
CT.TranDate between '20190801' and '20190831' and
CT.[Status] <> 'A' and
CT.IsCanel = 1
where FT.TranDate >= '20190801' and and
FT.TranDate < '20190901'
FT.[Status] = 'A' AND
XP.FeeId in (SELECT val FROM dbo.f_split(#IDs, ',')) and
(FT.IsCancel = 0 or FT.IsCancel IS NULL) and
FT.EntryBy = 'rajan'
Group By convert(char(10), FT.TranDate, 126)
Then for this version, you specifically an index on FeeTransaction(EntryBy, Status, TranDate, Cancel).
Note the following changes:
You do not need to aggregate Patient_Account as a subquery. Window functions are quite convenient.
Your date comparisons preclude the use of indexes. Converting dates to strings is a bad practice in general.
You have over-used isnull().
I assume that the appropriate indexes are in place for the joins.
I would use STRING_SPLIT and Common Table Expressions and do away with date conversions:
Declare #IDs nvarchar(max)='1,4,5,6,8,9,43,183'
;WITH CTE_ID AS
(
SELECT value AS ID FROM STRING_SPLIT(#IDs, ',');)
),
MaxPatient
AS
(
SELECT MAX(P.Id) [Id], P.TranMainId, isnull(SUM(P.AmtToPay),0) [Amt]
From Patient_Account P
Group By P.TranMainId
)
SELECT isnull(isnull(SUM(FT.PaidAmt),0) - isnull(SUM(CT.PaidAmt),0),0) As [Amount],
convert(char(10),FT.TranDate,126) [Date]
FROM FeeTransaction FT
INNER JOIN MaxPatient PA
ON FT.Id = PA.TranMainId
INNER JOIN Patient_Account XP
ON PA.Id = XP.Id
INNER JOIN Master_Fee MF
ON XP.FeeId = MF.Id
INNER Join Master_Patient MP
ON FT.PID = MP.Id
INNER JOIN Master_FeeType TY
ON MF.FeeTypeId = TY.Id
INNER JOIN CTE_ID
ON XP.FeeId = CTE_ID.ID
LEFT JOIN FeeTransaction CT
ON FT.TransactionId = CT.TransactionId AND
CT.TranDate >= '20190801' AND CT.TranDate < '20190831' AND
CT.[Status] <> 'A' AND isnull(CT.IsCancel,0) = 1
WHERE FT.TranDate >= '20190801' and FT.TranDate < '20190831' AND
FT.[Status] = 'A' AND
ISNULL(FT.IsCancel,0) = 0 AND
FT.EntryBy = 'rajan'
GROUP BY CAST(FT.TranDate AS Date)
Not only is your query slow, but it appear that it is giving incorrect output.
i) When you are not using any column of Patient_Account in your resultset then why are you writing this sub query?
Select max(P.Id) [Id], P.TranMainId, isnull(SUM(P.AmtToPay),0) [Amt]
From Patient_Account P
Group By P.TranMainId
ii) Avoid using <>.So Status must be either 'A' or 'I'
so write this instead CT.[Status] = 'I'
iii) What is the correct data type of TranDate ?Don't use function in where condition. .
iv) No need of isnull(CT.IsCancel,0) = 1,instead write CT.IsCancel = 1
So my script is just outline, but it is easy to understand.
Declare #IDs nvarchar(max)='1,4,5,6,8,9,43,183'
create table #temp(id int)
insert into #temp(id)
SELECT val FROM dbo.f_split(#IDs, ',')
declare #FromDate Datetime='2019-08-01'
declare #toDate Datetime='2019-08-31'
-- mention all column of FeeTransaction that you need in this query along with correct data type
-- Store TranDate in this manner convert(char(10),FT.TranDate,126) in this table
create table #Transaction()
select * from FeeTransaction FT
where FT.TranDate>=#FromDate and FT.TranDate<#toDate
and exists(select 1 from #temp t where t .val=ft.id)
-- mention all column of Patient_Account that you need in this query along with correct data type
create table #Patient_Account()
Select max(P.Id) [Id], P.TranMainId, isnull(SUM(P.AmtToPay),0) [Amt]
From Patient_Account P
where exists(select 1 from #Transaction T where t.id=PA.TranMainId)
Group By P.TranMainId
SELECT isnull(isnull(SUM(FT.PaidAmt),0) - isnull(SUM(CT.PaidAmt),0),0) [Amount], TranDate [Date]
from #Transaction FT
Inner Join #Patient_Account XP ON PA.Id = XP.Id
Inner Join Master_Fee MF ON XP.FeeId = MF.Id
INNER Join Master_Patient MP ON FT.PID = MP.Id
Inner Join Master_FeeType TY ON MF.FeeTypeId = TY.Id
Left JOIN #Transaction CT on FT.TransactionId = CT.TransactionId AND CT.[Status] = 'I' AND CT.IsCancel = 1
Where AND FT.[Status] = 'A' AND XP.FeeId in (SELECT val FROM #temp t)
AND FT.IsCancel = 0 AND FT.EntryBy = 'rajan'
Group By TranDate
I have query to select data from related tables.
SELECT
s.id,
CASE
WHEN count(DISTINCT e.id) <> 0
THEN count(DISTINCT o.id) / count(DISTINCT e.id)
END OrdersAverageNumber
FROM
[School] s
JOIN
[SchoolStore] ss ON ss.SchoolId = s.Id
JOIN
[Event] e ON e.SchoolId = ss.SchoolId
AND e.IsDeleted = 0
AND e.Status = 1
AND e.Date >= #startDate
AND e.Date <= #endDate
JOIN
[Order] o ON o.EventId = e.id
AND o.OrderStatus = 1
AND o.CreatedDate >= #startDate
AND o.CreatedDate <= #endDate
GROUP BY
s.id;
But I can't understand what I need to change to update all OrdersAverageNumber records in School table with values from selection above.
You can use update:
with q as (< your query here >)
update s
set OrdersAverageNumber = q.OrdersAverageNumber
from school s join
q
on s.id = q.id;
I need to select extra columns from another table in my sql query.
SELECT
d.UnitID,
b.BookingID,
d.ProjectID,
b.ClientName,
(SELECT LetterTypeID
FROM Letters
WHERE ProjectID = 27 AND BookingID = b.BookingID)
FROM
ScheduledDues AS d
INNER JOIN
Booking AS b ON d.BookingID = b.BookingID
INNER JOIN
Units AS u ON d.UnitID = u.UnitID
WHERE
d.ProjectID = 27
AND DueFrom <= GETDATE()
GROUP BY
d.BookingID, d.UnitID, d.ProjectID,
u.UnitNo, b.ClientName
HAVING
SUM(DueTill) = 0
How can I do this? and have it in group by. Is selecting LetterTypeID possible?
Need to use LetterTypeID in group by like below or You can fetch results without letters table into temp and join it with letters to get LetterTypeID
SELECT d.UnitID,
b.BookingID,
d.ProjectID,
b.ClientName,
l.LetterTypeID
FROM ScheduledDues AS d INNER JOIN
Booking AS b ON d.BookingID = b.BookingID INNER JOIN
Units AS u ON d.UnitID = u.UnitID INNER JOIN
Letters AS l ON b.BookingID=l.BookingID AND l.ProjectID=27
WHERE d.ProjectID = 27 AND
DueFrom <= GETDATE()
GROUP BY d.BookingID,
d.UnitID,
d.ProjectID,
u.UnitNo,
b.ClientName,
l.LetterTypeID
HAVING SUM(DueTill) = 0
Can you try this query
SELECT BookingID, UnitID, ProjectID
UnitNo, ClientName ,LetterTypeID FROM (SELECT
d.UnitID,
b.BookingID,
d.ProjectID,
b.ClientName,
DueTill,
(SELECT LetterTypeID
FROM Letters
WHERE ProjectID = 27 AND BookingID = b.BookingID) LetterTypeID
FROM
ScheduledDues AS d
INNER JOIN
Booking AS b ON d.BookingID = b.BookingID
INNER JOIN
Units AS u ON d.UnitID = u.UnitID
WHERE
d.ProjectID = 27
AND DueFrom <= GETDATE()) x
GROUP BY
BookingID, UnitID, ProjectID,
UnitNo, ClientName ,LetterTypeID
HAVING
SUM(DueTill) = 0
Hey so my query right now is
ALTER PROCEDURE [SSRS].[VolumeCustomers]
#UserID int
AS
select
CaseTypeName,
COUNT(CaseNo) as CaseCount,
'Open' as indicator
FROM ORDERS.ApCase AC with (NOLOCK)
join ORDERS.CaseType CT (NOLOCK) on CT.CaseTypeID = AC.CaseTypeID
join WORKFLOW.WorkflowHistory WH (NOLOCK) on WH.EntityID = AC.CaseID and TableID = dbo.GetTableID('ApCase', 'ORDERS') and WH.Active = 1
inner join WORKFLOW.WorkflowStep WS (NOLOCK) on WS.WorkflowStepID = WH.WorkflowStepID and WS.NextStepID is null
where (AC.Active =1 and AC.CreatedDate >= DATEADD(day,-7,getdate()) and AC.CreatedDate < GETDATE())
Group By CaseTypeName
union
select
CaseTypeName,
COUNT(Caseno) as CaseCount,
'Closed' as indicator
FROM ORDERS.ApCase AC with (NOLOCK)
join ORDERS.CaseType CT (NOLOCK) on CT.CaseTypeID = AC.CaseTypeID
join WORKFLOW.WorkflowHistory WH (NOLOCK) on WH.EntityID = AC.CaseID and TableID = dbo.GetTableID('ApCase', 'ORDERS') and WH.Active = 1
join WORKFLOW.WorkflowStep WS (NOLOCK) on WS.WorkflowStepID = WH.WorkflowStepID and WS.NextStepID is not null
where (AC.Active =1 and AC.CreatedDate >= DATEADD(day,-7,getdate()) and AC.CreatedDate < GETDATE())
GROUP BY CaseTypeName
Order by CaseCount desc
and the out put is
Cytogenetics 2 All
Cytogenetics 1 Open
Flow Tech 1 All
Flow Tech 1 Open
Surgical 1 All
Surgical 1 Open
But i want the cytogenetics, flow tech, and surgical to all appear on the same row
example:
Cytogenetics 2 All 1 Open
Flow Tech 1 All 1 Open
Surgical 1 All 1 Open
How do I edit my query to reflect this?
Does this work?
SELECT A.*, B.CaseCount, B.indicator
FROM (<First Part of Union in Question>) AS A INNER JOIN
(<Second Part of Union in Question>) AS B ON A.CaseTypeName = B.CaseTypeName
SELECT
CaseTypeName,
COUNT(CASE WHEN WS.NextStepID IS NULL THEN Caseno END) AS CaseCountOpen,
COUNT(CASE WHEN WS.NextStepID IS NOT NULL THEN Caseno END) AS CaseCountClosed,
COUNT(CaseNo) AS CaseCountAll
FROM ORDERS.ApCase AC with (NOLOCK)
JOIN ORDERS.CaseType CT (NOLOCK)
ON CT.CaseTypeID = AC.CaseTypeID
JOIN WORKFLOW.WorkflowHistory WH (NOLOCK)
ON WH.EntityID = AC.CaseID
AND TableID = dbo.GetTableID('ApCase', 'ORDERS')
AND WH.Active = 1
JOIN WORKFLOW.WorkflowStep WS (NOLOCK)
ON WS.WorkflowStepID = WH.WorkflowStepID
WHERE AC.Active = 1
AND AC.CreatedDate >= DATEADD(day,-7,getdate())
AND AC.CreatedDate < GETDATE()
GROUP BY CaseTypeName
ORDER BY CaseCountAll DESC