SQL select command consume 100% CPU while executing - sql

In my query I'm Selecting row by row closing balance. It's consume 100% CPU while executing is sql server 2014.
Here is my query:
;WITH summary(id,reference_id,entry_date,particular,remarks,debit,credit,balance)AS(
SELECT
id,
reference_id,
entry_date,
particular,
remarks,
debit,
credit,
(credit-debit)+(SELECT ISNULL(SUM(l.credit-l.debit) ,0) FROM member_transaction l WHERE l.entry_date<a.entry_date AND l.member_id=#mId AND is_succeed=1 AND isnull(l.reference_id,0) NOT IN(SELECT user_reference_id FROM recharge_request WHERE status='Failure'))AS balance
FROM member_transaction a
WHERE member_id=#mId AND is_succeed=1
AND isnull(reference_id,0) NOT IN(SELECT user_reference_id FROM recharge_request WHERE status='Failure')),
openingbalance(
id,
reference_id,
entry_date,
particular,
remarks,
debit,
credit,
balance
)AS(SELECT TOP 1 0,'','','OPENING BALANCE','',0,0,balance FROM summary WHERE entry_date<'2017/03/10' ORDER BY entry_date DESC
)SELECT * FROM openingbalance UNION SELECT * FROM summary ORDER BY entry_date DESC
Is there any other way to calculate row by row closing balance on every transaction? Please help me to solve this problem.
HERE is table structure:
CREATE TABLE [member_transaction](
[id] [int] IDENTITY(1,1) NOT NULL,
[member_id] [int] NULL,
[t_type] [varchar](50) NULL,
[debit] [decimal](12, 2) NOT NULL,
[credit] [decimal](12, 2) NOT NULL,
[particular] [varchar](100) NULL,
[remarks] [varchar](150) NULL,
[reference_id] [varchar](50) NULL,
[entry_date] [datetime] NOT NULL,
[is_succeed] [bit] NOT NULL
)
CREATE TABLE [recharge_request](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[mobile_no] [varchar](50) NULL,
[amount] [decimal](12, 0) NULL,
[user_reference_id] [varchar](50) NULL,
[uid] [int] NULL,
[rdate] [datetime] NOT NULL,
[status] [varchar](50) NOT NULL
)

Assuming you're in SQL Server 2012+, you should try something like this:
SELECT
id,
reference_id,
entry_date,
particular,
remarks,
debit,
credit,
sum(isnull(credit,0)-isnull(debit,0)) over (order by entry_date asc) AS balance
FROM
member_transaction a
WHERE
member_id=#mId AND
is_succeed=1 AND
not exist (select 1 FROM recharge_request r WHERE r.user_reference_id = a.reference_id and r.status='Failure')
If you want to fetch more than one member, then you should have partition by in the over part of the sum.

Related

Joining CTE_1 to CTE_2 if CTE_2 has data, if not just give CTE_1 Data

Is there a way to join CTE_1 to CTE_2 if CTE_2 has data? With this code, it returns nothing if CTE_2 has no data. The common columns are Names and Locations. The issue that I am having is CTE_1 will always have data, but CTE_2 won't get data until around 4-6 hours into the shift.
Begin
Create table #Punches
(
[AEmployeeID] [varchar](255) NULL,
[APERSONFULLNAME] [varchar](255) NULL,
[ACUSTOMER] [varchar](255) NULL,
[ADEPARTMENT] [varchar](255) NULL,
[AEVENTDATE] [varchar](255) NULL,
[AINPUNCHDTM1] [varchar](255) NULL,
[AOUTPUNCHDTM1] [varchar](255) NULL,
[AINPUNCHDTM2] [varchar](255) NULL,
[AOUTPUNCHDTM2] [varchar](255) NULL,
[AINPUNCHDTM3] [varchar](255) NULL,
[AOUTPUNCHDTM3] [varchar](255) NULL,
[ASUPERVISORNAME] [varchar](255) NULL,
[ASUPERVISORID] [varchar](255) NULL,
[ASHIFTSTARTTIME] [varchar](255) NULL,
[ASHIFTENDTIME] [varchar](255) NULL,
[ASITE] [varchar](255) NULL,
[ABadge#] [varchar] (255) NULL
)
insert into #Punches
EXECUTE ('BEGIN FX_RPTSP_MEMPHIS_PUNCHES(); END;') at KR1P1;
end
Begin
Create table #1stScans
(
ID int identity ,
[AEmployee Name] [varchar](255) NULL,
[Location] [varchar](25) NULL,
[Dispatch] [varchar](30) NULL,
[TimeStamp] [varchar](255) NULL
)
insert into #1stScans
Select * from Openquery(FFLOW,'Execute rudpBenchLocations_today');
end
--Selects Tech Name, Bench Location, 1st Punch, First Scan, and Dwell (COMPLETED and ACCURATE)
BEGIN
WITH CTE_1 AS(
Select
[AEmployee Name] Name1,
Location Location1,
#Punches.AINPUNCHDTM1 as FirstPunch,
Timestamp From
(Select [AEmployee Name],Location,TimeStamp,
ROW_NUMBER()OVER (PARTITION By [AEmployee Name] ORDER BY Timestamp ASC)Dup from #1stScans,#Punches)as FSD
Join #Punches ON [AEmployee Name]=APERSONFULLNAME
where FSD.dup = 1
AND Convert(Date,AINPUNCHDTM1) = Convert(Date,Getdate()))
,CTE_2 AS
(
Select [AEmployee Name] Name2,Location Location2,TimeStamp Timestamp2,AINPUNCHDTM2 LunchPunch,(ROW_NUMBER()OVER(PARTITION By [AEmployee Name] ORDER BY TimeStamp))as DUP from #1stScans
INNER JOIN #Punches ON [AEmployee Name]=APERSONFULLNAME
AND CONVERT(TIME,Timestamp)>=CONVERT(TIME,AINPUNCHDTM2)
)
***Select
Name1 as Name,
Location1 as Location,
TimeStamp as [1st TimeStamp],
FirstPunch,
TimeStamp2 as [2nd TimeStamp],
LunchPunch
FROM CTE_1
Join CTE_2 on Name1 = NAME2
WHERE DUP=1
AND Name2 <> ''***
END
Drop table #Punches
Drop table #1stScans
With a left join, conditions on the right hand table go in the JOIN conditions, not the where clause
Select
Name1 as Name,
Location1 as Location,
TimeStamp as [1st TimeStamp],
FirstPunch,
TimeStamp2 as [2nd TimeStamp],
LunchPunch
FROM CTE_1
LEFT Join CTE_2
on Name1 = NAME2
AND DUP=1
AND Name2 <> ''

How do I aggregate 3 columns that are different with MIN(DATE)?

I'm facing a simple problem here that I can't solve, I have this query:
SELECT
MIN(TEA_InicioTarefa),
PFJ_Id_Analista,
ATC_Id,
SRV_Id
FROM
dbo.TarefaEtapaAreaTecnica
INNER JOIN Tarefa t ON t.TRF_Id = TarefaEtapaAreaTecnica.TRF_Id
WHERE SRV_Id = 88
GROUP BY SRV_Id, ATC_Id, PFJ_Id_Analista
ORDER BY ATC_Id ASC
It returns me this:
I was able to group it a little with GROUP BY SRV_Id, ATC_Id, PFJ_Id_Analista that gave me these 8 records, but as you can see some PFJ_Id_Analista are different.
What I want is to select only the early date of each SRV_Id and ATC_Id, the PFJ_Id_Analista don't need to grup, if I remove PFJ_Id_Analista from the grouping the query works, but I need the column.
For eg.: between row number 2 and 3 I want only the early date, so it will be row 2. The same goes for rows 5 to 8, I want only row 6.
DDL for TarefaEtapaAreaTecnica (important key: TRF_Id)
CREATE TABLE [dbo].[TarefaEtapaAreaTecnica](
[TEA_Id] [int] IDENTITY(1,1) NOT NULL,
**[TRF_Id] [int] NOT NULL,**
[ETS_Id] [int] NOT NULL,
[ATC_Id] [int] NOT NULL,
[TEA_Revisao] [int] NOT NULL,
[PFJ_Id_Projetista] [int] NULL,
[TEA_DoctosQtd] [int] NULL,
[TEA_InicioTarefa] [datetime2](7) NULL,
[PFJ_Id_Analista] [int] NULL,
[TEA_FimTarefa] [datetime2](7) NULL,
[TEA_HorasQtd] [numeric](18, 1) NULL,
[TEA_NcfQtd] [int] NULL,
[PAT_Id] [int] NULL
DDL for Tarefa (important keys TRF_Id and SRV_Id (which I need it)):
CREATE TABLE [dbo].[Tarefa](
**[TRF_Id] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,**
**[SRV_Id] [int] NOT NULL,**
[TRT_Id] [int] NOT NULL,
[TRF_Descr] [varchar](255) NULL,
[TRF_Entrada] [datetime] NOT NULL,
[TRF_DoctosQtd] [int] NOT NULL,
[TRF_Devolucao] [datetime] NULL,
[TRF_NcfQtd] [int] NULL,
[TRF_EhDocInsuf] [bit] NULL,
[TRF_Observ] [varchar](255) NULL,
[TRF_AreasTrfQtd] [int] NULL,
[TRF_AreasTrfLiqQtd] [int] NULL
Thanks a lot.
EDIT:
CORRECT QUERY
Based on #Gordon Linoff post:
select t.TEA_InicioTarefa, t.PFJ_Id_Analista, t.ATC_Id, t.SRV_Id
from (select t.*,
row_number() over (partition by ATC_Id, SRV_Id
order by TEA_InicioTarefa) as seqnum, ta.SRV_Id
from dbo.TarefaEtapaAreaTecnica t
inner join dbo.Tarefa ta on t.TRF_Id = ta.TRF_Id
) t
where seqnum = 1 AND t.SRV_Id = 88
Just use window functions:
select t.*
from (select t.*,
row_number() over (partition by ATC_Id, SRV_Id
order by ini) as seqnum
from dbo.TarefaEtapaAreaTecnica t
) t
where seqnum = 1;
This is really an example of filtering, not aggregation. The problem is getting the right value to filter on.
Then get the grouping first and then do a JOIN with it like
SELECT
x.Min_TEA_InicioTarefa,
t.PFJ_Id_Analista,
t.ATC_Id,
t.SRV_Id
FROM
dbo.TarefaEtapaAreaTecnica t
INNER JOIN Tarefa ta ON ta.TRF_Id = t.TRF_Id
INNER JOIN (
select SRV_Id, MIN(TEA_InicioTarefa) as Min_TEA_InicioTarefa
from dbo.TarefaEtapaAreaTecnica
GROUP BY SRV_Id
) x ON t.SRV_Id = x.SRV_Id
WHERE t.SRV_Id = 88
ORDER BY t.ATC_Id ASC;

Subquery with Sum of top X rows

I am trying to get the top 5 results for each person from a table. I am able to get the top result for them however I want the sum of the top 5.
Select Distinct
r.LastName,
r.FirstName ,
r.Class,
r.BibNum,
(Select top 1 r2.points from Results r2 where r2.season=r.Season and r2.Mountain=r.Mountain and r2.Bibnum=r.bibnum Order By r2.Points Desc) as Points
from Results as r Where Season='2015' and Mountain='Ski Resort'
Order By Class, Points Desc
Columns:
[Id] [int] IDENTITY(1,1) NOT NULL,
[RaceNum] [int] NOT NULL,
[BibNum] [int] NOT NULL,
[FirstName] [nvarchar](max) NULL,
[LastName] [nvarchar](max) NULL,
[Sex] [nvarchar](max) NULL,
[Class] [nvarchar](max) NULL,
[Team] [nvarchar](max) NULL,
[FirstRun] [nvarchar](max) NULL,
[SecondRun] [nvarchar](max) NULL,
[Best] [nvarchar](max) NULL,
[Points] [int] NOT NULL,
[Season] [int] NOT NULL,
[Mountain] [nvarchar](max) NULL
You could use row_number() to get the top five rows, and then group by the other fields:
SELECT LastName,
FirstName,
Class,
BibNum,
SUM(points)
FROM (SELECT LastName,
FirstName,
Class,
BibNum,
points,
ROW_NUMBER() OVER (PARTITION BY LastName,
FirstName,
Class,
BibNum
ORDER BY points DESC) AS rn
FROM results
WHERE Season='2015' and Mountain='Ski Resort'
) t
WHERE rn <= 5
GROUP BY LastName, FirstName, Class, BibNum

SQL fastest 'GROUP BY' script

Is there any difference in how I edit the GROUP BY command?
my code:
SELECT Number, Id
FROM Table
WHERE(....)
GROUP BY Id, Number
is it faster if i edit it like this:
SELECT Number, Id
FROM Table
WHERE(....)
GROUP BY Number , Id
it's better to use DISTINCT if you don't want to aggregate data. Otherwise, there is no difference between the two queries you provided, it'll produce the same query plan
This examples are equal.
DDL:
CREATE TABLE dbo.[WorkOut]
(
[WorkOutID] [bigint] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[TimeSheetDate] [datetime] NOT NULL,
[DateOut] [datetime] NOT NULL,
[EmployeeID] [int] NOT NULL,
[IsMainWorkPlace] [bit] NOT NULL,
[DepartmentUID] [uniqueidentifier] NOT NULL,
[WorkPlaceUID] [uniqueidentifier] NULL,
[TeamUID] [uniqueidentifier] NULL,
[WorkShiftCD] [nvarchar](10) NULL,
[WorkHours] [real] NULL,
[AbsenceCode] [varchar](25) NULL,
[PaymentType] [char](2) NULL,
[CategoryID] [int] NULL
)
Query:
SELECT wo.WorkOutID, wo.TimeSheetDate
FROM dbo.WorkOut wo
GROUP BY wo.WorkOutID, wo.TimeSheetDate
SELECT DISTINCT wo.WorkOutID, wo.TimeSheetDate
FROM dbo.WorkOut wo
SELECT wo.DateOut, wo.EmployeeID
FROM dbo.WorkOut wo
GROUP BY wo.DateOut, wo.EmployeeID
SELECT DISTINCT wo.DateOut, wo.EmployeeID
FROM dbo.WorkOut wo
Execution plan:

Return rows which have same data in three columns

I have a table with the following schema
CREATE TABLE [dbo].[personas](
[id_persona] [int] IDENTITY(1,1) NOT NULL,
[nombres] [nvarchar](50) NOT NULL,
[apellido_paterno] [nvarchar](50) NULL,
[apellido_materno] [nvarchar](50) NULL,
[fecha_nacimiento] [date] NOT NULL,
[sexo] [varchar](1) NOT NULL,
[estado_civil] [nvarchar](50) NOT NULL,
[calle] [nvarchar](200) NULL,
[colonia] [nvarchar](100) NULL,
[codigo_postal] [char](5) NOT NULL,
[telefonos] [varchar](50) NULL,
[celular] [varchar](25) NULL,
[email] [varchar](50) NULL,
)
How do I make a query in SQL Server to return rows where nombre, apellido_paterno and apellido_materno are repeated? I mean two or more rows have the same data in these columns.
I suppose I'm looking something opposite to DISTINCT clause
You would want...
SELECT nombre, apellido_paterno, apellido_materno
FROM dbo.personas
GROUP BY nombre, apellido_paterno, apellido_materno
HAVING COUNT(*) > 1
If you want to look at the actual rows, then use that as an inner query and join onto it. So, something like
SELECT *
FROM personas pOuter INNER JOIN
(SELECT nombre, apellido_paterno, apellido_materno
FROM dbo.personas
GROUP BY nombre, apellido_paterno, apellido_materno
HAVING COUNT(*) > 1) pInner
ON pInner.nombre = pOuter.nombre
AND pInner.apellido_paterno = pOuter.apellido_paterno
AND pInner.apellido_materno = pOuter.apellido_materno
;WITH x AS
(
SELECT id_personas, rn = ROW_NUMBER() OVER
(
PARTITION BY nombre, apellido_paterno, apellido_materno
ORDER BY id_personas
)
FROM dbo.personas
)
SELECT <col list>
FROM dbo.personas AS p
WHERE EXISTS
(
SELECT 1 FROM x
WHERE x.id_personas = p.id_personas
AND x.rn > 1
);