쿼리가 매우 느리게 실행되고 있습니다. 더 이상 개선 할 방법이 있습니까?


9

다음과 같은 쿼리가 있으며 많은 SUM함수 호출로 인해 쿼리가 너무 느리게 실행됩니다. 데이터베이스에 많은 레코드가 있으며 각 연도에 대한 현재 연도 및 작년 (최근 30 일, 지난 90 일 및 지난 365 일)의 보고서를 받고 싶습니다.

SELECT 
    b.id as [ID]
    ,d.[Title] as [Title]
    ,e.Class as [Class]

    ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 30 Days Col1]
    ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 30 Days Col2]

    ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 90 Days Col1]
    ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 90 Days Col2]

    ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 365 Days Col1]
    ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 365 Days Col2]

    ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 30 Days Col1]
    ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 30 Days Col2]

    ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 90 Days Col1]
    ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 90 Days Col2]

    ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 365 Days Col1]
    ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 365 Days Col2]


    FROM 
    tb1 a
INNER JOIN 
    tb2 b on a.id=b.fid and a.col3 = b.col4
INNER JOIN 
    tb3 c on b.fid = c.col5
INNER JOIN       
    tb4 d on c.id = d.col6
INNER JOIN 
    tb5 e on c.col7 = e.id
GROUP BY
    b.id, d.Title, e.Class

누구나 빠른 실행을 위해 쿼리를 개선하는 방법을 알고 있습니까?

편집 :DATEADD 함수 호출을 where문 으로 옮기고 처음 2 년 동안로드 한 다음 열로 필터링하도록 제안되었지만 제안 된 답변이 실행되고 작동하는지 확실하지 않습니다. https : //.com/stackoverflow. com / a / 59944426 / 12536284

위의 솔루션에 동의하는 경우 현재 쿼리에 어떻게 적용 할 수 있습니까?

참고로 C #, Entity Framework (DB-First) 에서이 SP를 사용하고 있습니다.

var result = MyDBEntities.CalculatorSP();

4
처형 계획을 보여주십시오.
Dale K

1
무엇이든 -쿼리 속도를 늦출 수있는 것
Fabio


2
다시 실행 계획을 게시하십시오.
SQL 경찰

2
아직도 우리는 보이지 않습니다 Execution Plan. 게시하십시오
Arun Palanisamy

답변:


10

이미 언급했듯이이 경우 실행 계획 이 실제로 도움이 될 것입니다. 표시된 내용에 따라에서 총 15 개의 열 중 12 개의 열을 추출한 것으로 보이 tb1 (a)므로 조인없이 쿼리를 실행 tb1하여 쿼리가 예상대로 작동하는지 확인할 수 있습니다. SUM 함수 호출에 아무런 문제가 없으므로 조인에 문제가 있다고 생각합니다. 다음을 수행하는 것이 좋습니다. 당신은 마지막 예를 들어 가입 제외하여 시작할 수 INNER JOIN tb5 e on c.col7 = e.id와 같은 그것의 모든 관련 사용 e.Class as [Class]e.Class당신의 그룹에서 진술로. 우리는 그것을 완전히 배제하지는 않을 것입니다. 이것은 쿼리가 더 잘 실행되고 예상대로 임시 테이블을 마지막 조인 대신 임시 해결책으로 사용할 수있는 경우 문제가 있는지 여부를 확인하는 테스트 일뿐입니다. , 이 같은:

SELECT *
INTO #Temp
FROM
  (
     select * from tb5
  ) As tempTable;

SELECT 
    b.id as [ID]
    ,d.[Title] as [Title]
    ,e.Class as [Class]

    -- SUM Functions

FROM 
    tb1 a
INNER JOIN 
    tb2 b on a.id=b.fid and a.col3 = b.col4
INNER JOIN 
    tb3 c on b.fid = c.col5
INNER JOIN       
    tb4 d on c.id = d.col6
INNER JOIN 
    #Temp e on c.col7 = e.id
GROUP BY
    b.id, d.Title, e.Class

실제로 임시 테이블은 SQL Server에 임시로 존재하는 테이블입니다. 임시 테이블은 여러 번 액세스되는 즉시 결과 집합을 저장하는 데 유용합니다. 여기에 대한 자세한 내용은 https://www.sqlservertutorial.net/sql-server-basics/sql-server-temporary-tables/ 그리고 여기 https://codingsight.com/introduction-to-temporary-tables-in -sql-server /

또한 난 강력하게 추천 할 것입니다 당신이 저장 프로 시저를 사용하는 경우는 설정 NOCOUNT하는 ON네트워크 트래픽이 크게 감소하기 때문에, 그것은 또한 상당한 성능 향상을 제공 할 수 있습니다 :

SET NOCOUNT ON
SELECT *
INTO #Temp
-- The rest of code

을 바탕으로 :

SET NOCOUNT ON은 T-SQL 쿼리 문의 영향을받는 행 수를 표시하는 메시지를 방지하는 set 문입니다. 영향을받는 행 메시지가 표시되지 않도록 저장 프로 시저 및 트리거 내에서 사용됩니다. 저장 프로 시저 내에서 SET NOCOUNT ON을 사용하면 저장 프로 시저의 성능이 크게 향상 될 수 있습니다.


1
전체 tb5#Temp테이블에 복사 하고 임시 테이블을 조인하는 것이 tb5직접 조인보다 더 빠른 이유를 설명해 주 시겠습니까? 분명히 그들은 동일한 데이터를 포함합니다 (및 #Temp에 존재하는 경우 색인이 누락 될 수 있음 tb5). 왜 이것이 더 효율적인지 이해할 수 없습니다 (모든 데이터를 복사 하고 결합 하는 것이 덜 효율적이어야한다는 것을 알고 있습니다 ).
지그

2
@zig이 경우에 맞지만 tb5다른 서버에 있으면 어떻게됩니까? 이 경우 임시 테이블을 사용하는 것이 다른 서버에 직접 조인하는 것보다 확실히 빠릅니다. 그것은 과거에 비슷한 상황이 있었는지 테스트하고 변경했는지 확인하기위한 제안 일뿐입니다. 운행 테이블 이이 경우에도 OP에 도움이 된 것으로 보입니다.
살라 악바리

2

가장 좋은 방법은 테이블 변수 / 해시 테이블에 삽입하는 것입니다 (행 수가 적은 경우 테이블 변수를 사용하거나 행 수가 매우 큰 경우 해시 테이블을 사용하십시오). 그런 다음 집계를 업데이트 한 다음 마지막으로 테이블 변수 또는 해시 테이블에서 선택하십시오. 쿼리 계획을 조사해야합니다.

DECLARE @MYTABLE TABLE (ID INT, [Title] VARCHAR(500), [Class] VARCHAR(500),
[Current - Last 30 Days Col1] INT, [Current - Last 30 Days Col2] INT,
[Current - Last 90 Days Col1] INT,[Current - Last 90 Days Col2] INT,
[Current - Last 365 Days Col1] INT, [Current - Last 365 Days Col2] INT,
[Last year - Last 30 Days Col1] INT, [Last year - Last 30 Days Col2] INT,
[Last year - Last 90 Days Col1] INT, [Last year - Last 90 Days Col2] INT,
[Last year - Last 365 Days Col1] INT, [Last year - Last 365 Days Col2] INT)



INSERT INTO @MYTABLE(ID, [Title],[Class], 
[Current - Last 30 Days Col1], [Current - Last 30 Days Col2],
[Current - Last 90 Days Col1], [Current - Last 90 Days Col2],
[Current - Last 365 Days Col1], [Current - Last 365 Days Col2],
[Last year - Last 30 Days Col1], [Last year - Last 30 Days Col2],
[Last year - Last 90 Days Col1], [Last year - Last 90 Days Col2],
[Last year - Last 365 Days Col1], [Last year - Last 365 Days Col2]
  )
SELECT    b.id  ,d.[Title] ,e.Class ,0,0,0,0,0,0,0,0,0,0,0,0        
FROM     tb1 a
INNER JOIN   tb2 b on a.id=b.fid and a.col3 = b.col4
INNER JOIN   tb3 c on b.fid = c.col5
INNER JOIN   tb4 d on c.id = d.col6
INNER JOIN  tb5 e on c.col7 = e.id
GROUP BY b.id, d.Title, e.Class

UPDATE T 
SET [Current - Last 30 Days Col1]=K.[Current - Last 30 Days Col1] , 
[Current - Last 30 Days Col2]    =K.[Current - Last 30 Days Col2],
[Current - Last 90 Days Col1]    = K.[Current - Last 90 Days Col1], 
[Current - Last 90 Days Col2]    =K.[Current - Last 90 Days Col2] ,
[Current - Last 365 Days Col1]   =K.[Current - Last 365 Days Col1], 
[Current - Last 365 Days Col2]   =K.[Current - Last 365 Days Col2],
[Last year - Last 30 Days Col1]  =K.[Last year - Last 30 Days Col1],
 [Last year - Last 30 Days Col2] =K.[Last year - Last 30 Days Col2],
[Last year - Last 90 Days Col1]  =K.[Last year - Last 90 Days Col1], 
[Last year - Last 90 Days Col2]  =K.[Last year - Last 90 Days Col2],
[Last year - Last 365 Days Col1] =K.[Last year - Last 365 Days Col1],
 [Last year - Last 365 Days Col2]=K.[Last year - Last 365 Days Col2]
    FROM @MYTABLE T JOIN 
     (
SELECT 
    b.id as [ID]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col1 ELSE 0 END),0) as [Current - Last 30 Days Col1]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col2 ELSE 0 END),0) as [Current - Last 30 Days Col2]

    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col1 ELSE 0 END),0) as [Current - Last 90 Days Col1]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col2 ELSE 0 END),0) as [Current - Last 90 Days Col2]

    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END),0) as [Current - Last 365 Days Col1]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END),0) as [Current - Last 365 Days Col2]

    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col1 ELSE 0 END),0) as [Last year - Last 30 Days Col1]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col2 ELSE 0 END),0) as [Last year - Last 30 Days Col2]

    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col1 ELSE 0 END),0) as [Last year - Last 90 Days Col1]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col2 ELSE 0 END),0) as [Last year - Last 90 Days Col2]

    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END),0) as [Last year - Last 365 Days Col1]
    ,ISNULL(Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END),0) as [Last year - Last 365 Days Col2]
    FROM     tb1 a
INNER JOIN   tb2 b on a.id=b.fid and a.col3 = b.col4
INNER JOIN   tb3 c on b.fid = c.col5
INNER JOIN   tb4 d on c.id = d.col6
INNER JOIN  tb5 e on c.col7 = e.id
GROUP BY    b.id
) AS K ON T.ID=K.ID


SELECT *
FROM @MYTABLE

0

tb1이 큰 테이블이라고 가정합니다 (tb2, tb3, tb4 및 tb5에 상대적).

그렇다면 해당 테이블의 선택을 제한하는 것이 좋습니다 (WHERE 절 사용).

예를 들어 tb2, tb3, tb4 및 tb5와의 조인이 필요한 행을 몇 퍼센트로 줄이므로 tb1의 작은 부분 만 사용하는 경우 테이블이 조인에 사용하는 열에서 색인화되는지 확인해야합니다. .

tb1의 많은 부분이 사용되면 결과를 tb2, tb3, tb4 및 tb5에 결합하기 전에 결과를 그룹화하는 것이 좋습니다. 아래는 그 예입니다.

SELECT 
    b.id as [ID]
    ,d.[Title] as [Title]
    ,e.Class as [Class]
    ,SUM(a.[Current - Last 30 Days Col1]) AS [Current - Last 30 Days Col1]
    ,SUM(a.[Current - Last 30 Days Col2]) AS [Current - Last 30 Days Col2]
    ,SUM(a.[Current - Last 90 Days Col1]) AS [Current - Last 90 Days Col1]
    -- etc.
    FROM (
      SELECT a.id, a.col3

      ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 30 Days Col1]
      ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 30 Days Col2]

      ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 90 Days Col1]
      ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 90 Days Col2]

      ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Current - Last 365 Days Col1]
      ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Current - Last 365 Days Col2]

      ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 30 Days Col1]
      ,Sum(CASE WHEN a.DateCol >= DATEADD(MONTH,-13,GETDATE()) and a.DateCol <= DATEADD(MONTH,-12,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 30 Days Col2]

      ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 90 Days Col1]
      ,Sum(CASE WHEN a.DateCol >= DATEADD(QUARTER,-5,GETDATE()) and a.DateCol <= DATEADD(QUARTER,-4,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 90 Days Col2]

      ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col1 ELSE 0 END) as [Last year - Last 365 Days Col1]
      ,Sum(CASE WHEN a.DateCol >= DATEADD(YEAR,-2,GETDATE()) and a.DateCol <= DATEADD(YEAR,-1,GETDATE()) THEN a.col2 ELSE 0 END) as [Last year - Last 365 Days Col2]

      FROM  tb1 a
      WHERE a.DateCol >= DATEADD(YEAR,-2,GETDATE())
      GROUP BY a.id, a.col3
    ) AS a
INNER JOIN 
    tb2 b on a.id=b.fid and a.col3 = b.col4
INNER JOIN 
    tb3 c on b.fid = c.col5
INNER JOIN       
    tb4 d on c.id = d.col6
INNER JOIN 
    tb5 e on c.col7 = e.id
GROUP BY
    b.id, d.Title, e.Class

실행 계획을 먼저 본 다음 인덱스 생성 및 통계 재생성에 대한 결정을 내리는 것이 훨씬 좋습니다.
SQL 경찰

나는 왜 내 게시물이 아무런 이유없이 부정적인 점수를 얻는 것을 싫어합니다. 물론 성능 문제의 핵심에 도달하려면 실행 계획을 검사해야한다는 데 동의합니다. 나는 쿼리와 관련된 외래 키의 인덱스를 확인하는 것에 대한 권장 사항을지지합니다.
Gert-Jan 1

1
당신은 몰라도 무언가를 "가정"합니다. 그래서 당신은 미지의 것에 기초하여 답변을 게시합니다. 따라서 공감. 실행 계획을 게시하여 OP에게 질문을 개선하도록 지시하는 것이 좋습니다.
SQL 경찰

내가 쓴 전부는 아닙니다. 개인적으로, 나는 단지 동의하지 않을 때가 아니라 대답이 나쁘거나 틀린 경우에만 공감합니다. 그러나 응답 해 주셔서 감사합니다.
Gert-Jan 1

어떻게하면 그것이 틀렸다는 것을 증명할 수 있습니까?
SQL 경찰


0

이러한 계산을 최적화하기 위해 일부 값을 미리 계산하는 것이 좋습니다. 사전 계산의 개념은 읽거나 진행해야하는 행 수를 줄이는 것입니다.

이를 달성하는 한 가지 방법은 인덱싱 된 뷰를 사용 하고 엔진 자체에서 계산을 수행하도록하는 것입니다. 이 유형의 뷰에는 몇 가지 제한이 있으므로 간단한 테이블을 작성하고 대신 계산을 수행해야합니다. 기본적으로 비즈니스 요구에 따라 다릅니다.

따라서 아래 예에서는 RowIDRowDatetime열이 있는 테이블을 만들고 백만 개의 행을 삽입 하고 있습니다. 인덱싱 된 뷰를 사용하여 일별 엔터티를 계산하므로 연간 백만 행을 쿼리하는 대신 연간 365 행을 쿼리하여 이러한 메트릭을 계산합니다.

DROP TABLE IF EXISTS [dbo].[DataSource];
GO

CREATE TABLE [dbo].[DataSource]
(
    [RowID] BIGINT IDENTITY(1,1) PRIMARY KEY
   ,[RowDateTime] DATETIME2
);

GO

DROP VIEW IF EXISTS [dbo].[vw_DataSource];
GO

CREATE VIEW [dbo].[vw_DataSource] WITH SCHEMABINDING
AS
SELECT YEAR([RowDateTime]) AS [Year]
      ,MONTH([RowDateTime]) AS [Month]
      ,DAY([RowDateTime]) AS [Day]
      ,COUNT_BIG(*) AS [Count]
FROM [dbo].[DataSource]
GROUP BY YEAR([RowDateTime])
        ,MONTH([RowDateTime])
        ,DAY([RowDateTime]);
GO

CREATE UNIQUE CLUSTERED INDEX [IX_vw_DataSource] ON [dbo].[vw_DataSource]
(
    [Year] ASC,
    [Month] ASC,
    [Day] ASC
);

GO

DECLARE @min bigint, @max bigint
SELECT @Min=1 ,@Max=1000000

INSERT INTO [dbo].[DataSource] ([RowDateTime])
SELECT TOP (@Max-@Min+1) DATEFROMPARTS(2019,  1.0 + floor(12 * RAND(convert(varbinary, newid()))), 1.0 + floor(28 * RAND(convert(varbinary, newid())))          )       
FROM master..spt_values t1 
CROSS JOIN master..spt_values t2

GO


SELECT *
FROM [dbo].[vw_DataSource]


SELECT SUM(CASE WHEN DATEFROMPARTS([Year], [Month], [Day]) >= DATEADD(MONTH,-1,GETDATE()) THEN [Count] ELSE 0 END) as [Current - Last 30 Days Col1]
      ,SUM(CASE WHEN DATEFROMPARTS([Year], [Month], [Day]) >= DATEADD(QUARTER,-1,GETDATE()) THEN [Count] ELSE 0 END) as [Current - Last 90 Days Col1]
      ,SUM(CASE WHEN DATEFROMPARTS([Year], [Month], [Day]) >= DATEADD(YEAR,-1,GETDATE()) THEN [Count] ELSE 0 END) as [Current - Last 365 Days Col1]
FROM [dbo].[vw_DataSource];

이러한 솔루션의 성공은 데이터가 분산되는 방식과 보유한 행 수에 따라 크게 달라집니다. 예를 들어, 일 년에 하루에 하나의 항목이있는 경우보기와 테이블의 행이 동일하게 일치하므로 I / O 조작이 줄어들지 않습니다.

또한 위의 내용은 데이터를 구체화하고 읽는 예입니다. 귀하의 경우보기 정의에 더 많은 열을 추가해야 할 수도 있습니다.


0

조회 테이블 "Dates"테이블을 사용하여 DatesId의 인덱스와 데이터를 조인합니다. 기록 데이터를 찾아 볼 때 날짜를 필터로 사용합니다. 조인이 빠르므로 DatesId가 클러스터 된 기본 인덱스 (기본 키)이므로 필터링됩니다. 데이터 테이블의 날짜 열 (포함 된 열)도 추가하십시오.

날짜 테이블에는 다음과 같은 열이 있습니다.

DatesId, Date, Year, Quarter, YearQuarter, MonthNum, MonthNameShort, YearWeek, WeekNum, DayOfYear, DayOfMonth, DayNumOfWeek, DayName

데이터 예 : 20310409 2031-04-09 2031 2 2031-Q2 4 월 4 일 2031_15 15 99 9 3 수요일

csv를 원하는 경우 PM으로 가져와 데이터베이스로 가져올 수 있지만 온라인에서 이와 같은 것을 쉽게 찾아서 직접 만들 수 있다고 확신합니다.

각 날짜의 정수를 얻을 수 있도록 ID 열도 추가합니다. 따라서 작업하기가 조금 더 쉬워 지지만 요구 사항은 아닙니다.

SELECT * FROM dbo.dates where dateIndex BETWEEN (getDateIndexDate(getDate())-30 AND getDateIndexDate(getDate())+0) --30 days ago

이를 통해 특정 기간으로 쉽게 돌아갈 수 있습니다. 이것에 대한 자신의 견해를 만드는 것은 매우 쉽습니다. 물론 ROW_NUMBER () 함수를 사용하여 몇 년, 몇 주 등 동안이 작업을 수행 할 수도 있습니다.

원하는 날짜 범위가 있으면 데이터에 가입합니다. 매우 빠르게 작동합니다!


0

항상 전체 개월 수를 기준으로 값을 그룹화하므로 from 절의 하위 쿼리에서 월별로 그룹화합니다. 이것은 임시 테이블을 사용하는 것과 유사합니다. 이것이 실제로 쿼리 속도를 높일 지 확실하지 않습니다.

SELECT f.id, f.[Title], f.Class,
    SUM(CASE WHEN f.MonthDiff = 1 THEN col1 ELSE 0 END) as [Current - Last 30 Days Col1],
    -- etc
FROM (
    SELECT 
        b.id,
        d.[Title],
        e.Class,
        DateDiff(Month, a.DateCol, GETDATE()) as MonthDiff,
        Sum(a.col1) as col1,
        Sum(a.col2) as col2
    FROM  tb1 a
    INNER JOIN tb2 b on a.id = b.fid and a.col3 = b.col4
    INNER JOIN tb3 c on b.fid = c.col5
    INNER JOIN tb4 d on c.id = d.col6
    INNER JOIN tb5 e on c.col7 = e.id
    WHERE a.DateCol between DATEADD(YEAR,-2,GETDATE() and GETDATE()
    GROUP BY b.id, d.Title, e.Class, DateDiff(Month,  a.DateCol, GETDATE())
) f
group by f.id, f.[Title], f.Class

-2

SQL 쿼리 속도를 향상 시키려면 인덱스를 추가해야합니다. 조인 된 각 테이블마다 하나의 인덱스를 추가해야합니다.

oracle에 대한 다음 코드 예제와 같이

CREATE INDEX supplier_idx
ON supplier (supplier_name);

이것은 나쁜 제안이 아닙니다. OP에서 임시 테이블이 색인없이 생성됨을 알 수 있습니다-c.col7 = e.id의 INNER JOIN #Temp e. 답변의 개선의 여지가 있지만, 나는 그것이 공동으로 downvoted되어야한다고 생각하지 않습니다. 특히 새로운 사용자를 위해.
smoore4

@ smoore4 동의합니다. 명확한 인수없이이 다운 보팅 옵션을 제거해야합니다. 이 기능의 큰 오용이 있습니다
Greggz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.