Các truy vấn đang thực hiện rất chậm, có cách nào để cải thiện nó nữa không?


9

Tôi có truy vấn sau và vì có rất nhiều SUMlệnh gọi hàm, truy vấn của tôi chạy quá chậm. Tôi có rất nhiều hồ sơ trong cơ sở dữ liệu của mình và tôi muốn nhận báo cáo từ năm hiện tại và năm ngoái (30 ngày qua, 90 ngày qua và 365 ngày qua) cho mỗi người:

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

Có ai có ý tưởng làm thế nào tôi có thể cải thiện truy vấn của mình để chạy nhanh hơn không?

EDIT: Tôi được khuyến khích chuyển lệnh DATEADDgọi hàm sang wherecâu lệnh và tải hai năm đầu tiên sau đó lọc chúng trong các cột, nhưng tôi không chắc câu trả lời được đề xuất được thực thi và hoạt động, nó có thể được tìm thấy ở đây: https: // stackoverflow. com / a / 59944426/12536284

Nếu bạn đồng ý với giải pháp trên, vui lòng chỉ cho tôi cách tôi có thể áp dụng nó trong truy vấn hiện tại của mình?

Chỉ cần FYI, tôi đang sử dụng SP này trong C #, Entity Framework (DB-First), đại loại như thế này:

var result = MyDBEntities.CalculatorSP();

4
Cho chúng tôi xem kế hoạch thực hiện của bạn ...
Dale K

1
TRÊN bất cứ điều gì - là những gì có thể làm cho truy vấn chậm
Fabio


2
Một lần nữa, xin vui lòng gửi kế hoạch thực hiện.
Cảnh sát SQL

2
Tuy nhiên, chúng tôi không nhìn thấy Execution Plan. Xin vui lòng gửi nó
Arun Palanisamy

Câu trả lời:


10

Như đã được đề cập, kế hoạch thực hiện sẽ thực sự hữu ích trong trường hợp này. Dựa trên những gì bạn đã thể hiện, có vẻ như bạn đã trích xuất 12 cột trong tổng số 15 cột từ đó tb1 (a), vì vậy bạn có thể thử chạy truy vấn của mình mà không cần tham gia và chỉ cần tb1xem liệu truy vấn của bạn có hoạt động như mong đợi hay không. Vì tôi có thể thấy không có gì sai với các lệnh gọi hàm SUM của bạn, tôi đoán tốt nhất là bạn có vấn đề với các phép nối của mình, tôi sẽ đề nghị làm như sau. Bạn có thể bắt đầu bằng cách loại trừ lần tham gia cuối cùng, INNER JOIN tb5 e on c.col7 = e.idvà mọi cách sử dụng liên quan của nó như e.Class as [Class]e.Classtrong nhóm của bạn bằng tuyên bố. Chúng tôi sẽ không loại trừ hoàn toàn, đây chỉ là một thử nghiệm để đảm bảo liệu vấn đề có xảy ra hay không, nếu truy vấn của bạn chạy tốt hơn và như mong đợi, bạn có thể thử sử dụng bảng tạm thời như một cách giải quyết thay vì tham gia cuối cùng , một cái gì đó như thế này:

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

Trên thực tế, các bảng tạm thời là các bảng tồn tại tạm thời trên SQL Server. Các bảng tạm thời rất hữu ích để lưu trữ các tập kết quả ngay lập tức được truy cập nhiều lần. Bạn có thể đọc thêm về nó ở đây https://www.sqlservertutorial.net/sql-server-basics/sql-server-tceed-tables/ Và tại đây https://codingsight.com/int sinhtion-to-t tạm-tests-in -sql-máy chủ /

Ngoài ra tôi rất muốn giới thiệu, nếu bạn đang sử dụng Stored Procedure, thiết lập NOCOUNTđể ON, nó cũng có thể cung cấp một tăng hiệu suất đáng kể, bởi vì lưu lượng mạng sẽ giảm đáng kể:

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

Dựa trên điều này :

SET NOCOUNT ON là một câu lệnh được thiết lập để ngăn chặn thông báo hiển thị số lượng hàng bị ảnh hưởng bởi các câu lệnh truy vấn T-SQL. Điều này được sử dụng trong các thủ tục được lưu trữ và kích hoạt để tránh hiển thị thông báo hàng bị ảnh hưởng. Sử dụng SET NOCOUNT ON trong một thủ tục được lưu trữ có thể cải thiện hiệu suất của thủ tục được lưu trữ bằng một mức đáng kể.


1
Bạn có thể giải thích tại sao sao chép toàn bộ tb5vào #Tempbảng và tham gia bảng tạm thời hoạt động nhanh hơn so với tham gia tb5trực tiếp không? chắc chắn chúng chứa cùng một dữ liệu (và #Tempcó thể thiếu chỉ mục nếu nó tồn tại tb5). Tôi thực sự không thể hiểu tại sao điều này hiệu quả hơn (đối với tất cả những gì tôi biết nên sao chép tất cả dữ liệu tham gia) sẽ kém hiệu quả hơn .
zig

2
@zig Bạn đúng trong trường hợp này, nhưng nếu cái đó tb5nằm ở máy chủ khác thì sao? Trong trường hợp này, sử dụng bảng tạm thời chắc chắn nhanh hơn so với tham gia trực tiếp vào máy chủ khác. Đó chỉ là một gợi ý để kiểm tra và xem liệu có gì thay đổi hay không, tôi đã có một tình huống tương tự trong quá khứ, và có vẻ như may mắn là bảng tạm thời đã giúp OP cũng trong trường hợp này.
Salah Akbari

2

Cách tiếp cận tốt nhất là chèn vào một bảng biến / bảng băm (nếu số lượng hàng nhỏ sử dụng biến bảng hoặc sử dụng bảng băm nếu số lượng hàng khá lớn). Sau đó cập nhật tổng hợp và cuối cùng chọn từ biến bảng hoặc bảng băm. Nhìn vào kế hoạch truy vấn là cần thiết.

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

Tôi giả sử tb1 là một bảng lớn (liên quan đến tb2, tb3, tb4 và tb5).

Nếu vậy, sẽ có ý nghĩa ở đây để hạn chế lựa chọn bảng đó (với mệnh đề WHERE).

Nếu chỉ sử dụng một phần nhỏ của tb1, ví dụ vì các phép nối với tb2, tb3, tb4 và tb5 giảm các hàng cần thiết xuống chỉ còn vài phần trăm, thì bạn nên kiểm tra xem các bảng có được lập chỉ mục trên các cột bạn sử dụng trong các liên kết không .

Nếu một phần lớn của tb1 được sử dụng, thì có thể có ý nghĩa để nhóm các kết quả của nó trước khi nối nó với tb2, tb3, tb4 và tb5. Dưới đây là một ví dụ về điều đó.

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

Trước tiên, sẽ tốt hơn nhiều khi xem kế hoạch thực hiện và sau đó đưa ra quyết định về việc tạo chỉ mục và tạo lại các số liệu thống kê.
Cảnh sát SQL

Tôi thực sự ghét rằng bài viết của tôi bị điểm âm mà không có lời giải thích tại sao. Tất nhiên tôi đồng ý rằng để đi vào trọng tâm của vấn đề hiệu suất, người ta phải kiểm tra kế hoạch thực hiện. Có nói rằng, tôi đứng trước khuyến nghị của tôi về việc kiểm tra các chỉ mục cho bất kỳ khóa ngoại nào có liên quan trong truy vấn.
Gert-

1
Bạn "giả sử" một cái gì đó mà không biết. Vì vậy, bạn gửi một câu trả lời trên cơ sở chưa biết. Do đó downvote. Tốt hơn là hướng dẫn OP cải thiện câu hỏi của mình bằng cách đăng kế hoạch thực hiện.
Cảnh sát SQL

Đó không phải là tất cả những gì tôi viết. Cá nhân, tôi sẽ chỉ downvote nếu câu trả lời là xấu hoặc sai, không phải khi tôi chỉ đơn giản là không đồng ý. Nhưng cảm ơn đã phản hồi.
Gert-

Theo một cách nào đó là sai, bởi vì làm thế nào bạn có thể chứng minh nó là đúng?
Cảnh sát SQL


0

Để tối ưu hóa các tính toán như vậy, người đàn ông xem xét tính toán trước một số giá trị. Ý tưởng của tính toán trước là giảm số lượng hàng cần đọc hoặc tiến hành.

Một cách để đạt được điều này là sử dụng chế độ xem được lập chỉ mục và để động cơ tự thực hiện các phép tính. Vì kiểu xem này có một số hạn chế, cuối cùng bạn sẽ tạo một bảng đơn giản và thực hiện các phép tính thay thế. Về cơ bản, nó phụ thuộc vào nhu cầu kinh doanh.

Vì vậy, trong ví dụ dưới đây tôi đang tạo ra một bảng với RowIDRowDatetimecột và chèn 1 triệu hàng. Tôi đang sử dụng chế độ xem được lập chỉ mục để đếm các thực thể mỗi ngày, vì vậy thay vì truy vấn 1 triệu hàng mỗi năm, tôi sẽ truy vấn 365 hàng mỗi năm để đếm các số liệu này.

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];

Thành công của giải pháp này phụ thuộc rất nhiều vào cách phân phối dữ liệu và số lượng hàng bạn có. Ví dụ: nếu bạn có một mục nhập mỗi ngày cho mỗi ngày trong năm, chế độ xem và bảng sẽ có cùng một hàng, do đó, các thao tác I / O sẽ không bị giảm.

Ngoài ra, ở trên chỉ là một ví dụ về việc cụ thể hóa dữ liệu và đọc nó. Trong trường hợp của bạn, bạn có thể cần thêm nhiều cột định nghĩa xem.


0

Tôi sẽ sử dụng bảng tra cứu "Ngày" để tham gia dữ liệu của mình với chỉ mục trên DatesId. Tôi sử dụng ngày làm bộ lọc khi tôi muốn duyệt dữ liệu lịch sử. Phép nối nhanh và do đó, quá trình lọc như DatesId được phân cụm chỉ mục chính (khóa chính). Thêm cột ngày (như cột bao gồm) cho bảng dữ liệu của bạn.

Bảng ngày có các cột sau:

DatesId, Ngày, Năm, Quý, YearQuarter, MonthNum, MonthNameShort, YearWeek, WeekNum, DayOfYear, DayOfMonth, DayNumOfWeek, DayName

Dữ liệu mẫu: 20310409 2031-04-09 2031 2 2031-Q2 4 tháng 4 năm 2031_15 15 99 9 3 Thứ tư

Bạn có thể PM cho tôi nếu bạn muốn có một csv này để bạn có thể nhập nó vào cơ sở dữ liệu, nhưng tôi chắc chắn rằng bạn có thể dễ dàng tìm thấy một cái gì đó như thế này trực tuyến và làm cho riêng bạn.

Tôi cũng thêm một cột danh tính để bạn có thể nhận được một số nguyên cho mỗi ngày. Điều này làm cho nó dễ dàng hơn để làm việc với, nhưng không phải là một yêu cầu.

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

Điều này cho phép tôi dễ dàng quay trở lại một khoảng thời gian nhất định. Thật dễ dàng để tạo quan điểm của riêng bạn về điều này. Tất nhiên, bạn cũng có thể sử dụng hàm ROW_NUMBER () để thực hiện việc này trong nhiều năm, nhiều tuần, v.v.

Khi tôi có tài liệu tôi muốn, tôi tham gia vào dữ liệu. Hoạt động rất nhanh!


0

Vì bạn luôn nhóm các giá trị dựa trên toàn bộ số tháng, nên trước tiên tôi sẽ nhóm theo tháng trong một truy vấn con trong mệnh đề from. Điều này tương tự như sử dụng một bảng tạm thời. Không chắc chắn nếu điều này thực sự sẽ tăng tốc truy vấn của bạn.

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

Để cải thiện tốc độ truy vấn SQL, bạn phải thêm chỉ mục. Đối với mỗi bảng đã tham gia, bạn phải thêm một chỉ mục.

Giống như ví dụ mã này cho oracle:

CREATE INDEX supplier_idx
ON supplier (supplier_name);

đây không phải là một gợi ý tồi bạn thấy từ OP rằng một bảng tạm thời được tạo không có chỉ mục - INNER THAM GIA #Temp e trên c.col7 = e.id. Trong khi có chỗ để cải thiện câu trả lời, tôi không nghĩ rằng nó nên bị hạ cấp xuống hàng loạt. đặc biệt cho một người dùng mới.
smoore4

@ smoore4 Đồng ý, nên loại bỏ tùy chọn này mà không có đối số rõ ràng. Có sự lạm dụng lớn chức năng này
Greggz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.