Click here to Skip to main content
15,886,199 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
i have the following query that takes more that 4 minutes to excute is there any other way to rewrite that query not that billsDetails table contains 100k record and Billtable contains 10k record


BillDetails table structure

BillDetailsID bigint not null "PK"
productID bigint null,
billID bigint null
BillType tinyint not null

BillsOperations table
BillID bigint not null "Pk"
ParentID bigint null "self relationship"
IsPermitted bit not null
BillType tinyint not null

SQL
SELECT * FROM (
SELECT 
b.BillID, b.Code,b.BillType,  dbo.Fn_BillNameByType(b.BillType) AS BillTypeName ,
(SELECT COUNT(BillDetailID) FROM dbo.BillsDetailsOperations WHERE BillID= b.BillID)   AS OriginalCount,


(
SELECT COUNT(DISTINCT ProductID) FROM dbo.BillsDetailsOperations
WHERE BillID IN (
SELECT BillID FROM dbo.BillsOperations WHERE ParentID = b.BillID AND BillType IN (9,10)))   AS PermittedCount

FROM dbo.BillsOperations  AS b
WHERE b.IsPermitted = 1 and b.BillType NOT IN (5,8,9,10)) AS detailsTbl
WHERE (detailsTbl.OriginalCount < detailsTbl.PermittedCount) OR (detailsTbl.OriginalCount > detailsTbl.PermittedCount) 


What I have tried:

i have tried to create group by but not working as i want
Posted
Updated 26-Sep-17 9:53am
v2
Comments
itsmypassion 25-Sep-17 7:01am    
Please specify table structure.
TheSniper105 25-Sep-17 7:06am    
i did
FranzBe 25-Sep-17 7:11am    
Did you already check the 'Include actual execution plan' option and have a look at the results?
TheSniper105 25-Sep-17 7:43am    
it takes much time when enable that option
Jörgen Andersson 27-Sep-17 4:57am    
Just curious.
You accepted my solution so it must have worked.
How much faster did it get?

First of all and most important, you need an index on BillDetails
SQL
CREATE NONCLUSTERED INDEX BillDetails_BillID_IX ON BillDetails (BillID) INCLUDE (productID)
And possibly also one on ParentID.

Secondly, avoid correlated subqueries as much as possible. Use joins instead.
Try this:
SQL
WITH j AS (
    SELECT  bo.ParentID
           ,bdp.productID
    FROM    dbo.BillsDetailsOperations bdp
    JOIN    dbo.BillsOperations bo ON bo.BillID = bdp.BillID
    WHERE   bo.BillType IN (9,10)
    )
,detailsTbl as (
    SELECT  b.BillID
           ,b.Code
           ,b.BillType
           ,dbo.Fn_BillNameByType(b.BillType) AS BillTypeName
           ,COUNT(bd.BillDetailID) AS OriginalCount
           ,COUNT(DISTINCT ProductID) AS PermittedCount
    FROM    dbo.BillsOperations  AS b
    LEFT JOIN   dbo.BillsDetailsOperations bd ON bd.BillID = b.BillID
    LEFT JOIN   j ON j.ParentID = b.BillID
    WHERE   b.IsPermitted = 1
        AND b.BillType NOT IN (5,8,9,10)
    GROUP BY b.BillID
           ,b.Code
           ,b.BillType
    )
SELECT  *
FROM    detailsTbl
WHERE   detailsTbl.OriginalCount != detailsTbl.PermittedCount 
 
Share this answer
 
v2
Hi

First of all in your case i would make the BillDetails.BillId Foreign Key.

and if i understud you correct this is my solution.

CREATE TABLE #BillsOperations (	BillID  [bigint], ParentID  [bigint] null,IsPermitted  [bigint] NULL,BillType  [bigint] NULL);
CREATE TABLE #BillDetails (	BillDetailsID   [bigint], productID   [bigint],billID   [bigint] NULL,BillType [bigint] NULL);
CREATE TABLE #BillType (ID   [bigint], descr nvarchar(100));
insert into #BillType (ID, descr) values (9,'INVOICE');
insert into #BillType (ID, descr) values (1,'CREDITNOTE');

insert into #BillsOperations (BillID, ParentID,IsPermitted,BillType) values (1,null,1,9);
insert into #BillsOperations (BillID, ParentID,IsPermitted,BillType) values (2,null,1,9);
insert into #BillsOperations (BillID, ParentID,IsPermitted,BillType) values (3,null,1,1);

insert into #BillDetails (BillDetailsID, productID,billID,BillType) values (1,1,1,9);
insert into #BillDetails (BillDetailsID, productID,billID,BillType) values (2,2,1,9);
insert into #BillDetails (BillDetailsID, productID,billID,BillType) values (3,3,1,9);
insert into #BillDetails (BillDetailsID, productID,billID,BillType) values (4,4,1,9);
insert into #BillDetails (BillDetailsID, productID,billID,BillType) values (5,1,2,9);
insert into #BillDetails (BillDetailsID, productID,billID,BillType) values (6,1,2,9);
insert into #BillDetails (BillDetailsID, productID,billID,BillType) values (7,2,2,9);
insert into #BillDetails (BillDetailsID, productID,billID,BillType) values (8,3,2,9);
insert into #BillDetails (BillDetailsID, productID,billID,BillType) values (9,1,3,1);
insert into #BillDetails (BillDetailsID, productID,billID,BillType) values (10,2,3,1);
insert into #BillDetails (BillDetailsID, productID,billID,BillType) values (11,1,3,1);

select * from (select 
a.BillID, a.BillType,  c.descr AS BillTypeName , count(*) AS OriginalCount,
case when a.BillType IN (9,10) then COUNT(DISTINCT b.ProductID) else 0 end AS PermittedCount

from #BillsOperations a inner join #BillDetails b on a.BillID=b.billID inner join #BillType c on a.BillType=c.ID
group by a.BillID, a.BillType,  c.descr) x
--WHERE (OriginalCount < PermittedCount) OR (OriginalCount > PermittedCount) 


drop table #BillsOperations;
drop table #BillDetails;
drop table #BillType;


Have a nice day
 
Share this answer
 
Comments
TheSniper105 26-Sep-17 0:38am    
not same query as i want

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900