Permintaan berjalan sangat lambat, apakah ada cara untuk memperbaikinya lebih lanjut?

9

Saya memiliki pertanyaan berikut, dan karena banyak SUMpanggilan fungsi, permintaan saya berjalan terlalu lambat. Saya memiliki banyak catatan di database saya dan saya ingin mendapatkan laporan dari tahun ini dan tahun lalu (30 hari terakhir, 90 hari terakhir dan 365 hari terakhir) untuk masing-masing:

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

Adakah yang tahu bagaimana cara meningkatkan kueri agar berjalan lebih cepat?

EDIT: Saya didorong untuk memindahkan DATEADDpemanggilan fungsi ke wherepernyataan dan memuat dua tahun pertama pertama kemudian menyaringnya dalam kolom, tapi saya tidak yakin jawaban yang disarankan dijalankan dan berfungsi, itu bisa ditemukan di sini: https: // stackoverflow. com / a / 59944426/12536284

Jika Anda setuju dengan solusi di atas, tolong tunjukkan kepada saya bagaimana saya bisa menerapkannya dalam permintaan saya saat ini?

Hanya FYI, saya menggunakan SP ini di C #, Entity Framework (DB-First), sesuatu seperti ini:

var result = MyDBEntities.CalculatorSP();
Jim
sumber
4
Tunjukkan pada kami rencana eksekusi Anda ...
Dale K
1
PADA apa pun - adalah apa yang dapat membuat permintaan menjadi lambat
Fabio
2
Sekali lagi, silakan posting rencana eksekusi.
SQL Police
2
Masih kita tidak melihat Execution Plan. Silakan mempostingnya
Arun Palanisamy

Jawaban:

10

Seperti yang telah disebutkan, rencana eksekusi akan sangat membantu dalam kasus ini. Berdasarkan apa yang Anda tunjukkan, tampaknya Anda telah mengekstraksi 12 kolom dari 15 kolom total tb1 (a), sehingga Anda dapat mencoba menjalankan kueri Anda tanpa bergabung dan hanya menentangnya tb1untuk melihat apakah kueri Anda berfungsi seperti yang diharapkan. Karena saya dapat melihat tidak ada yang salah dengan panggilan fungsi SUM Anda, tebakan terbaik saya adalah Anda memiliki masalah dengan gabungan Anda, saya akan menyarankan untuk melakukan hal berikut. Anda dapat mulai dengan mengecualikan bergabung terakhir misalnya, INNER JOIN tb5 e on c.col7 = e.iddan segala penggunaan terkait seperti e.Class as [Class]dane.Classdalam grup Anda dengan pernyataan. Kami tidak akan mengecualikannya sepenuhnya, ini hanya tes untuk memastikan apakah masalahnya ada atau tidak, jika kueri Anda berjalan lebih baik dan seperti yang diharapkan, Anda dapat mencoba menggunakan tabel temp sebagai solusi alih-alih bergabung terakhir , sesuatu seperti ini:

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

Sebenarnya, tabel sementara adalah tabel yang ada sementara di SQL Server. Tabel sementara berguna untuk menyimpan set hasil langsung yang diakses beberapa kali. Anda dapat membaca lebih lanjut tentang ini di sini https://www.sqlservertutorial.net/sql-server-basics/sql-server-turnal-tables/ Dan di sini https://codingsight.com/introduction-to-temporary-tables-in -sql-server /

Saya juga akan sangat menyarankan, jika Anda menggunakan Prosedur Tersimpan, atur NOCOUNTke ON, itu juga dapat memberikan peningkatan kinerja yang signifikan, karena lalu lintas jaringan sangat berkurang:

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

Berdasarkan ini :

SET NOCOUNT ON adalah pernyataan set yang mencegah pesan yang menunjukkan jumlah baris yang dipengaruhi oleh pernyataan permintaan T-SQL. Ini digunakan dalam prosedur tersimpan dan pemicu untuk menghindari menampilkan pesan baris yang terpengaruh. Menggunakan SET NOCOUNT ON dalam prosedur tersimpan dapat meningkatkan kinerja prosedur tersimpan dengan margin yang signifikan.

Salah Akbari
sumber
1
Bisakah Anda jelaskan mengapa menyalin seluruh tb5ke #Temptabel dan bergabung dengan tabel temp bekerja lebih cepat daripada bergabung tb5secara langsung? bermuka masam mereka mengandung data yang sama (dan #Tempmungkin hilang indeks jika itu ada di tb5). Saya benar-benar tidak mengerti mengapa ini lebih efisien (untuk semua yang saya tahu seharusnya lebih efisien untuk menyalin semua data dan bergabung).
zig
2
@zig Anda benar dalam hal ini, tetapi bagaimana jika tb5terletak di server lain? Dalam hal ini menggunakan tabel temp jelas lebih cepat daripada langsung bergabung ke server lain. Itu hanya saran untuk menguji dan melihat apakah ada yang berubah. Saya memiliki situasi yang sama di masa lalu, dan tampaknya untungnya tabel temp telah membantu OP juga dalam kasus ini.
Salah Akbari
2

Pendekatan terbaik adalah memasukkan ke dalam tabel variabel / tabel hash (jika jumlah baris kecil menggunakan variabel tabel atau menggunakan tabel hash jika jumlah baris cukup besar). Kemudian perbarui agregasi dan akhirnya pilih dari tabel variabel atau tabel hash. Diperlukan rencana kueri.

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
Harshana
sumber
0

Saya berasumsi tb1 adalah tabel besar (relatif terhadap tb2, tb3, tb4 dan tb5).

Jika demikian, masuk akal di sini untuk membatasi pemilihan tabel tersebut (dengan klausa WHERE).

Jika hanya sebagian kecil dari tb1 digunakan, misalnya karena bergabung dengan tb2, tb3, tb4 dan tb5 mengurangi baris yang dibutuhkan hanya beberapa persen, maka Anda harus memeriksa apakah tabel diindeks pada kolom yang Anda gunakan dalam gabungan. .

Jika sebagian besar tb1 digunakan, maka masuk akal untuk mengelompokkan hasilnya sebelum bergabung ke tb2, tb3, tb4 dan tb5. Di bawah ini adalah contohnya.

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
Gert-Jan
sumber
Akan jauh lebih baik untuk pertama-tama melihat rencana eksekusi, dan kemudian membuat keputusan untuk membuat indeks dan membuat ulang statistik.
SQL Police
Saya benar-benar benci posting saya mendapat skor negatif tanpa penjelasan mengapa. Tentu saja saya setuju bahwa untuk sampai ke inti masalah kinerja, kita harus memeriksa rencana eksekusi. Karena itu, saya mendukung rekomendasi saya tentang memeriksa indeks untuk kunci asing yang relevan dalam kueri.
Gert-
1
Anda "menganggap" sesuatu tanpa disadari. Jadi, Anda memposting jawaban berdasarkan hal yang tidak diketahui. Karena itu downvote. Lebih baik menginstruksikan OP untuk meningkatkan pertanyaannya dengan memposting rencana eksekusi.
SQL Police
Bukan itu yang saya tulis. Secara pribadi, saya hanya akan downvote jika jawabannya buruk atau salah, tidak ketika saya tidak setuju. Tapi terima kasih sudah merespons.
Gert-
Di satu sisi itu salah, karena bagaimana Anda bisa membuktikannya benar?
SQL Police
0

Cukup gunakan kolum terkomputasi

Contoh

ALTER TABLE tb1 ADD [Current - Last 30 Days Col1] AS (CASE WHEN a.DateCol >= DATEADD(MONTH,-1,GETDATE()) THEN a.col1 ELSE 0 END) PERSISTED;

Tentukan Kolom yang Dihitung dalam Tabel

Dawid Wekwejt
sumber
0

Untuk mengoptimalkan perhitungan seperti itu, Anda dapat mempertimbangkan untuk terlebih dahulu menghitung beberapa nilai. Gagasan pra-perhitungan adalah untuk mengurangi jumlah baris yang perlu dibaca atau diproses.

Salah satu cara untuk mencapai ini adalah menggunakan tampilan yang diindeks dan meninggalkan mesin untuk melakukan perhitungan dengan sendirinya. Karena jenis tampilan ini memiliki beberapa keterbatasan, Anda akhirnya membuat tabel sederhana dan melakukan perhitungan sebagai gantinya. Pada dasarnya, itu tergantung pada kebutuhan bisnis.

Jadi, dalam contoh di bawah ini saya membuat tabel dengan RowIDdan RowDatetimekolom dan memasukkan 1 juta baris. Saya menggunakan tampilan yang diindeks untuk menghitung entitas per hari, jadi alih-alih meminta 1 juta baris per tahun, saya akan meminta 365 baris per tahun untuk menghitung metrik ini.

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

Keberhasilan solusi semacam itu sangat tergantung pada bagaimana data didistribusikan dan berapa banyak baris yang Anda miliki. Misalnya, jika Anda memiliki satu entri per hari untuk setiap hari dalam setahun, tampilan dan tabel akan memiliki kecocokan baris yang sama, sehingga operasi I / O tidak akan berkurang.

Selain itu, di atas hanyalah contoh mematerialisasi data dan membacanya. Dalam kasus Anda, Anda mungkin perlu menambahkan lebih banyak kolom definisi tampilan.

Gotqn
sumber
0

Saya akan menggunakan tabel pencarian "Tanggal" untuk bergabung dengan data saya dengan indeks pada DatesId. Saya menggunakan tanggal sebagai filter ketika saya ingin menelusuri data historis. Gabung cepat dan penyaringan sebagai DatesId dikelompokkan indeks utama (primary key). Tambahkan kolom tanggal (termasuk kolom) untuk tabel data Anda juga.

Tabel tanggal memiliki kolom-kolom berikut:

Tanggal, Tanggal, Tahun, Kuartal, Tahun Kuarter, MonthNum, MonthName Short, YearWeek, WeekNum, DayOfYear, DayOfMonth, DayNumOfWeek, DayName

Contoh data: 20310409 2031-04-09 2031 2 2031-Q2 4 April 2031_15 15 99 9 3 Rabu

Anda dapat PM saya jika Anda ingin csv ini sehingga Anda dapat mengimpornya ke database, tapi saya yakin Anda dapat dengan mudah menemukan sesuatu seperti ini secara online dan membuat sendiri.

Saya menambahkan kolom identitas juga sehingga Anda bisa mendapatkan bilangan bulat untuk setiap tanggal. Ini membuatnya sedikit lebih mudah untuk dikerjakan, tetapi bukan keharusan.

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

Ini memungkinkan saya untuk dengan mudah melompat kembali ke periode tertentu. Sangat mudah untuk membuat pandangan Anda sendiri tentang ini. Tentu saja Anda dapat menggunakan fungsi ROW_NUMBER () untuk melakukan ini selama bertahun-tahun, minggu, dll.

Setelah saya memiliki daterange yang saya inginkan, saya bergabung ke data. Bekerja sangat cepat!

berbintang satu
sumber
0

Karena Anda selalu mengelompokkan nilai berdasarkan seluruh jumlah bulan, saya pertama kali akan mengelompokkan berdasarkan bulan dalam subquery di dalam dari klausa. Ini mirip dengan menggunakan tabel sementara. Tidak yakin apakah ini akan mempercepat permintaan Anda.

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
Jeremy Lakeman
sumber
-2

Untuk meningkatkan kecepatan permintaan SQL, Anda harus menambahkan indeks. Untuk setiap tabel yang digabung, Anda harus menambahkan satu indeks.

Seperti contoh kode ini untuk oracle:

CREATE INDEX supplier_idx
ON supplier (supplier_name);
pengguna12467638
sumber
ini bukan saran yang buruk. Anda melihat dari OP bahwa tabel temp dibuat tanpa indeks - INNER BERGABUNG #Temp e pada c.col7 = e.id. sementara ada ruang untuk perbaikan dalam jawaban, saya tidak berpikir itu harus diturunkan secara massal. khususnya untuk pengguna baru.
smoore4
@ smoore4 Setuju, opsi downvoting ini tanpa argumen yang jelas harus dihapus. Ada penyalahgunaan besar fungsi ini
Greggz