SQL 需要服务器 CE 优化帮助

SQL Server CE optimization help needed

首先,我不是 dba 管理员,也没有接受过 SQL 方面的正规培训,我只知道我从谷歌搜索和一些高中时被遗忘的旧知识。

其次,我认为,如果您可以使用 SQL 语句获取特定数据,那么就这样做,而不是在程序中翻找大量数据。

我想知道我的查询是否可以用我拥有的数据库结构进行优化。数据库结构无法更改,因为它是我继承的。

相关table结构(SQL服务器CE)

CREATE TABLE [Klanten] //Clients
(
   [ID] INT NOT NULL IDENTITY (14,1),
   [Code] NVARCHAR(5) NOT NULL,
   [Naam] NVARCHAR(100) NOT NULL,
   [Email] NVARCHAR(100),
   [Telefoon] NVARCHAR(30),
   [Bankrekening] NVARCHAR(50),
   [BTWNummer] NVARCHAR(50),
   [BTWRegime] INT,
   [Saldo] MONEY DEFAULT 0,
   [Actief] BIT NOT NULL DEFAULT 1,
   [PrijsNiveau] TINYINT
);

CREATE TABLE [Bestellingen] //Orders
(
   [ID] INT NOT NULL IDENTITY (5235,1),
   [KlantID] INT NOT NULL,
   [LeveringsDatum] DATETIME,
   [OpmaakDatum] DATETIME NOT NULL DEFAULT getdate(),
   [Status] TINYINT NOT NULL DEFAULT 0,
   [Opmerking] NVARCHAR(200),
   [BackOrder] INT,
   [BTWRegime] INT,
   [Referentie] NVARCHAR(50)
);

CREATE TABLE [Facturen] //Invoices
(
   [ID] INT NOT NULL IDENTITY (13200,1),
   [BestelID] INT NOT NULL,
   [OpmaakDatum] DATETIME NOT NULL DEFAULT getdate(),
   [BetaalDatum] DATETIME,
   [Status] TINYINT,
   [BetaalWijze] TINYINT DEFAULT 0
);

CREATE TABLE [FactuurDetails] //Invoice line details
(
   [FactuurID] INT NOT NULL,
   [ArtikelID] INT NOT NULL,
   [Hoeveelheid] SMALLINT NOT NULL,
   [Prijs] MONEY
);

CREATE TABLE [Artikels] //Productes
(
   [ID] INT NOT NULL IDENTITY (156,1),
   [Naam] NVARCHAR(100) NOT NULL,
   [Code] NVARCHAR(5) NOT NULL,
   [GroepID] INT,
   [StandaardWinstMarge] REAL,
   [MinimumWinstMarge] REAL,
   [Voorraad] SMALLINT DEFAULT 0,
   [MinimumVoorraad] SMALLINT DEFAULT 0,
   [DoosInhoud] SMALLINT DEFAULT 1000,
   [LaatsteWijziging] DATETIME NOT NULL DEFAULT getdate(),
   [Prijs1] MONEY DEFAULT 0,
   [Prijs2] MONEY DEFAULT 0,
   [Prijs3] MONEY DEFAULT 0,
   [Prijs4] MONEY DEFAULT 0,
   [Prijs5] MONEY DEFAULT 0,
   [Prijs6] MONEY DEFAULT 0,
   [Actief] BIT NOT NULL DEFAULT 1,
   [KostPrijs] MONEY
);

我为这个数据库(实际上是任何数据库......)写了一个报告工具,它可以获取数据并在报告中很好地呈现它。我收到了一份报告的请求,该报告显示了在某一年内开具发票的所有客户的概况以及他们开具发票的总公斤数 ("hoeveelheid" * 产品 "doosinhoud")。然后在同一份报告中,每个客户每个产品的金额。

我想到了这 2 个查询

Select k.Naam, k.ID, COALESCE(sum(q.Kilos),0) as Kilos
From Klanten k
     left join Bestellingen b on b.KlantId = k.ID
     left join Facturen f on f.BestelId = b.Id
     left join (Select a.ID, fd.FactuurID As FactuurID, CAST((a.DoosInhoud / 1000.0 * fd.Hoeveelheid) AS MONEY) As Kilos
                from FactuurDetails fd
                inner join Artikels a on a.ID = fd.ArtikelID) as q on q.FactuurID = f.ID
Where f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1#
Group by k.Naam, k.ID


Select a.Naam, COALESCE(sum(fd.Hoeveelheid),0) as AantalGeFactureerd
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1#
group by a.Naam

我的报告程序在查询 运行(及其实际参数化)之前将 #anwser1# 更改为 userinput 并且 运行 是第一个查询返回的每个用户的第二个查询(更改在这种情况下,ID 的#identifier#。

这很好用而且速度很快(如果您认为它可以优化,请告诉我)。

现在是问题。 客户:这看起来不错。但是...你能不能也把它分成几个月。

所以我想出了这个用于第二个查询。它完成了工作,并且 运行 在笔记本电脑上实时数据库的副本上不到一秒钟,但它似乎有点……臃肿?

当你提出建议时,你能否也告诉我原因以及你正在使用的一些做法或思维方式的名称,以便我可以查找并实际学习一些东西?谢谢

Select tot.Naam as Naam, tot.Totaal as Totaal, jan.totaal as JAN, feb.totaal as FEB, mar.totaal as MAR,
       apr.totaal as APR, may.totaal as MAY, jun.totaal as JUN, jul.totaal as JUL, aug.totaal as AUG,
       sep.totaal as SEP, okt.totaal as OKT, nov.totaal as NOV, dec.totaal as DEC from
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1#
group by a.Naam) tot
left join
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1# And datepart(month,f.OpmaakDatum) = 1
group by a.Naam) jan on tot.Naam = jan.Naam
left join
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1# And datepart(month,f.OpmaakDatum) = 2
group by a.Naam) feb on tot.Naam = feb.Naam
left join
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1# And datepart(month,f.OpmaakDatum) = 3
group by a.Naam) mar on tot.Naam = mar.Naam
left join
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1# And datepart(month,f.OpmaakDatum) = 4
group by a.Naam) apr on tot.Naam = apr.Naam
left join
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1# And datepart(month,f.OpmaakDatum) = 5
group by a.Naam) may on tot.Naam = may.Naam
left join
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1# And datepart(month,f.OpmaakDatum) = 6
group by a.Naam) jun on tot.Naam = jun.Naam
left join
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1# And datepart(month,f.OpmaakDatum) = 7
group by a.Naam) jul on tot.Naam = jul.Naam
left join
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1# And datepart(month,f.OpmaakDatum) = 8
group by a.Naam) aug on tot.Naam = aug.Naam
left join
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1# And datepart(month,f.OpmaakDatum) = 9
group by a.Naam) sep on tot.Naam = sep.Naam
left join
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1# And datepart(month,f.OpmaakDatum) = 10
group by a.Naam) okt on tot.Naam = okt.Naam
left join
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1# And datepart(month,f.OpmaakDatum) = 11
group by a.Naam) nov on tot.Naam = nov.Naam
left join
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID
where k.ID = #Identifier# AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1# And datepart(month,f.OpmaakDatum) = 12
group by a.Naam) dec on tot.Naam = dec.Naam

LEFT JOIN 时,WHERE 子句中没有右侧 table 条件,将它们移到 ON 子句中,以获得真正的左连接行为。 (在 WHERE 中时,您会得到常规的内部联接结果。)

即类似于:

Select tot.Naam as Naam, tot.Totaal as Totaal, jan.totaal as JAN, feb.totaal as FEB, mar.totaal as MAR,
       apr.totaal as APR, may.totaal as MAY, jun.totaal as JUN, jul.totaal as JUL, aug.totaal as AUG,
       sep.totaal as SEP, okt.totaal as OKT, nov.totaal as NOV, dec.totaal as DEC from
(Select a.Naam as Naam, COALESCE(sum(fd.Hoeveelheid),0) as Totaal
from Artikels a
     left join FactuurDetails fd on fd.ArtikelID = a.ID
     left join Facturen f on fd.FactuurID = f.ID AND f.Status = 3 AND datepart(year,f.OpmaakDatum) = #Anwser1#
     left join Bestellingen b on f.BestelID = b.ID
     left join Klanten k on k.ID = b.KlantID AND k.ID = #Identifier# 
group by a.Naam) tot
... and so on ...