2016-02-02 3 views
0

Во-первых, я не администратор dba и не имею официального обучения в SQL, я знаю только то, что я знаю, от googling и некоторых старых забытых знаний из средней школы.Требуется помощь по оптимизации SQL Server CE

Во-вторых, я считаю, что если вы можете получить конкретные данные с помощью операторов SQL, тогда сделайте это, вместо того, чтобы рыться в большом наборе данных в вашей программе.

Я хочу знать, можно ли оптимизировать мой запрос с помощью структуры базы данных, которая у меня есть. Структура базы данных не может быть изменена, потому что это то, что я унаследовал.

Соответствующие структуры таблиц (SQL Server 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» * product «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 перед запрос выполняется (и на самом деле параметризованным) и запускаю второй запрос для каждого возвращенного пользователя первый запрос (изменение в этом случае # идентификатора # на идентификатор).

Это работает хорошо и быстро (если вы думаете, что его можно оптимизировать, скажите мне).

Теперь проблема. Клиент: Это выглядит хорошо. но ... можете ли вы разделить его в течение нескольких месяцев.

Так что я придумал это для второго запроса. Он выполняет свою работу, и он работает под вторым на ноутбуке на копии живой базы данных, но кажется немного ... раздутой?

Когда вы делаете предложение, не могли бы вы также рассказать мне, почему и, возможно, какие-то названия методов или способов мышления, которые вы используете, чтобы я мог найти его и научиться чему-то? Спасибо

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 
+0

Когда LEFT JOIN, не имеют условий правой стороны таблицы в предложении WHERE, переместите их в положение ON, чтобы получить истинное поведение влево. (Когда в ГДЕ вы получаете регулярный результат внутреннего соединения.) – jarlh

+0

Вы имеете в виду подзапросы? – Migaroez

+0

Да, у вас есть эта проблема в подзапросах. – jarlh

ответ

0

Когда LEFT JOIN, не имеют правильные условия стороны таблицы в пункте WHERE, переместите их в пункт ON вместо того, чтобы получить истинные левый присоединиться поведением. (Когда в WHERE, вы получаете регулярный результат внутреннего соединения.)

I.e. что-то вроде:

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 ... 
+0

Большое спасибо. предыдущее время исполнения: 749 мс, теперь 54 мс. – Migaroez

+0

Удивительно! На самом деле я не могу понять, почему ... – jarlh

+0

Я думаю, что это связано с тем, что теперь, когда пользователи находятся в предложениях on, требуется объединение более точных данных каждый раз, вместо того, чтобы сначала связывать все таблицы, а затем выполнять предложения where на гораздо большем наборе данных. Только мое предположение. Я хотел бы поговорить с кем-то, кто понимает этот корыто и через один день. – Migaroez

Смежные вопросы