Related
With the below function I getting the result as 00:09:10 however I want the result to be as 01:00:10.
So hours is considered as considered as 1 day.
Example if hours is 30 then it will be 03:03:00 and so on
fn_GetHolidayMinutes : Get holiday in minutes between two dates and country
CREATE FUNCTION [dbo].[fn_GetHolidayMinutes]
(#StartDate DATETIME,
#EndDate DATETIME,
#CountryId BIGINT)
RETURNS BIGINT
AS
BEGIN
DECLARE #OUTPUT BIGINT;
DECLARE #HolidayList TABLE (HolidaysDate DATE)
-- Create Table #HolidayList
-- (
-- HolidaysDate date
-- )
DECLARE #Date1 DATE, #Date2 DATE
DECLARE holiday_cursor CURSOR FOR
SELECT StartDate,EndDate
FROM Holidays
WHERE IsActive = 1
AND CountryId = #CountryId
AND ((StartDate BETWEEN #StartDate AND #EndDate) OR
(EndDate BETWEEN #StartDate AND #EndDate))
OPEN HOLIDAY_CURSOR
FETCH NEXT FROM HOLIDAY_CURSOR INTO #Date1, #Date2
WHILE ##FETCH_STATUS = 0
BEGIN
--INSERT INTO #HolidayList
INSERT INTO #HolidayList
SELECT DATEADD(DAY, number, #Date1) [Date]
FROM master..spt_values
WHERE type = 'P'
AND DATEADD(DAY, number, #Date1) <= #Date2
FETCH NEXT FROM HOLIDAY_CURSOR INTO #Date1, #Date2
END
CLOSE HOLIDAY_CURSOR;
DEALLOCATE HOLIDAY_CURSOR;
(SELECT #OUTPUT= COUNT(DISTINCT HolidaysDate)
FROM #HolidayList
WHERE HolidaysDate BETWEEN #StartDate AND #EndDate
AND DATEPART(dw, HolidaysDate) NOT IN (SELECT DISTINCT number
FROM master..spt_values
WHERE number BETWEEN 1 and 7
AND number NOT IN (SELECT WorkingDay
FROM WorkingDays
WHERE CountryId = #CountryId AND IsActive = 1)
))
---print #OUTPUT; --this will give in days
--get the output in minutes
RETURN #OUTPUT * (SELECT TOP 1 STUFF(WorkingHours, 2, 2, '')
FROM dbo.WorkingDays
WHERE CountryId = #CountryId) * 60;
END
fn_GetWorkingDayMinuts :
CREATE FUNCTION [dbo].[fn_GetWorkingDayMinuts]
(#StartDate DATETIME,
#EndDate DATETIME,
#CountryId BIGINT)
--RETURNS BIGINT
RETURNS VARCHAR(250)
AS
BEGIN
DECLARE #Temp BIGINT
SET #Temp = 0
DECLARE #FirstDay DATE
SET #FirstDay = CONVERT(DATE, #StartDate, 112)
DECLARE #LastDay DATE
SET #LastDay = CONVERT(DATE, #EndDate, 112)
DECLARE #StartTime TIME
SET #StartTime = CONVERT(TIME, #StartDate)
DECLARE #FinishTime TIME
SET #FinishTime = CONVERT(TIME, #EndDate)
DECLARE #WorkStart TIME
SET #WorkStart = (SELECT CONVERT(VARCHAR(5),CONVERT(TIME, CONVERT(VARCHAR,CONVERT(DATE, GETDATE()))+ ' ' + (SELECT TOP 1
WorkStartTime FROM WorkingDays WHERE CountryId=#CountryId), 120)))
DECLARE #WorkFinish TIME
SET #WorkFinish = (SELECT CONVERT(VARCHAR(5),CONVERT(TIME, CONVERT(VARCHAR,CONVERT(DATE, GETDATE()))+ ' ' + (SELECT TOP 1
WorkEndTime FROM WorkingDays WHERE CountryId=#CountryId), 120)))
DECLARE #DailyWorkTime BIGINT
SET #DailyWorkTime = DATEDIFF(MINUTE, #WorkStart, #WorkFinish)
IF (#StartTime<#WorkStart)
BEGIN
SET #StartTime = #WorkStart
END
IF (#FinishTime>#WorkFinish)
BEGIN
SET #FinishTime=#WorkFinish
END
IF (#FinishTime<#WorkStart)
BEGIN
SET #FinishTime=#WorkStart
END
IF (#StartTime>#WorkFinish)
BEGIN
SET #StartTime = #WorkFinish
END
DECLARE #CurrentDate DATE
SET #CurrentDate = #FirstDay
DECLARE #LastDate DATE
SET #LastDate = #LastDay
WHILE(#CurrentDate<=#LastDate)
BEGIN
--IF (DATEPART(dw, #CurrentDate)!=1 AND DATEPART(dw, #CurrentDate)!=7)
IF(DATEPART(dw, #CurrentDate) IN (SELECT distinct number FROM master..spt_values WHERE number BETWEEN 1 and 7
AND number NOT IN (SELECT
WorkingDay FROM WorkingDays where CountryId=#CountryId and IsActive=1)
))
BEGIN
IF (#CurrentDate!=#FirstDay) AND (#CurrentDate!=#LastDay)
BEGIN
SET #Temp = #Temp + #DailyWorkTime
END
--IF it starts at startdate and it finishes not this date find diff between work finish and start as minutes
ELSE IF (#CurrentDate=#FirstDay) AND (#CurrentDate!=#LastDay)
BEGIN
SET #Temp = #Temp + DATEDIFF(MINUTE, #StartTime, #WorkFinish)
END
ELSE IF (#CurrentDate!=#FirstDay) AND (#CurrentDate=#LastDay)
BEGIN
SET #Temp = #Temp + DATEDIFF(MINUTE, #WorkStart, #FinishTime)
END
--IF it starts and finishes in the same date
ELSE IF (#CurrentDate=#FirstDay) AND (#CurrentDate=#LastDay)
BEGIN
SET #Temp = DATEDIFF(MINUTE, #StartTime, #FinishTime)
END
END
SET #CurrentDate = DATEADD(day, 1, #CurrentDate)
END
-- Return the result of the function
IF #Temp<0
BEGIN
SET #Temp=0
END
--RETURN #Temp -(dbo.fn_GetHolidayMinutes (DATEADD(dd, 0, DATEDIFF(dd, 0, #StartDate)),DATEADD(dd, 0, DATEDIFF(dd, 0,
#EndDate)),#CountryId))
--RETURN #Temp
DECLARE #theMinutes INT
DECLARE #Result VARCHAR(250)
SET #theMinutes = #Temp -(dbo.fn_GetHolidayMinutes (DATEADD(dd, 0,
DATEDIFF(dd, 0, #StartDate)),DATEADD(dd, 0, DATEDIFF(dd, 0,
#EndDate)),#CountryId))
--SET #Result= concat((#theMinutes / 540),':' , (#theMinutes % 540) /
60, ':', (#theMinutes % 60))
SET #Result= concat((#theMinutes / ((SELECT TOP 1
STUFF(WorkingHours,2,2,'') FROM dbo.WorkingDays WHERE
CountryId=#CountryId) * 60)),':' , (#theMinutes % ((SELECT TOP 1
STUFF(WorkingHours,2,2,'') FROM dbo.WorkingDays WHERE
CountryId=#CountryId) * 60)) / 60, ':', (#theMinutes % 60))
RETURN #Result
END
So where to modify to the result as
BUSINESS HOURS CREATE DATE & TIME FIRST APPLY (DATE & TIME) TAT TIME CALCULATION RESULT
08h00-17h00: 9hrs/day 12-FEB-19 14:20 13-FEB-19 14:30 00:02:40 + 00:06:30 = 00:09:10 01:00:10
I have to find the missing hour in my table , for frequency = 1 I have to find a record per hour, if it's not the case, I have to display the missing hour.
here's my code
declare #StartDate datetime declare #EndDate datetime declare #now datetime set #now = getdate() set #StartDate = dateadd(day,-30,#now) set #EndDate = dateadd(day,-2,#now) Select Flow.Id,Flow.ComponentId, Frequency.Name frequencyName, Flow.MeasurementDate as MeasurementDate, LAG(MeasurementDate) OVER (ORDER BY MeasurementDate) LagValue, abs( DATEDIFF (hour, MeasurementDate, LAG(MeasurementDate) OVER (ORDER BY MeasurementDate) ) ) DifferenceDate , (CASE WHEN DATEDIFF (hour, MeasurementDate, LAG(MeasurementDate) OVER (ORDER BY MeasurementDate) ) > '1' THEN 'Yes' ELSE 'No' END) AS Gap into #tab1 FROM Data.dbo.Flow inner join Data.dbo.Component on flow.ComponentId = Component.Id inner join Data.dbo.Frequency on Flow.Frequency = Frequency.Id Where flow.LoaderCode='TOT' and Flow.Frequency='1' and ScheduledVolume IS NOT NULL and MeasurementDate between #StartDate and #EndDate --and DATEDIFF (hour, MeasurementDate, LAG(MeasurementDate) OVER (ORDER BY MeasurementDate) ) >1 Group By Frequency.Name, Flow.MeasurementDate, Flow.ComponentId select * from #tab1
--if i right understood then try this
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
DECLARE #now DATETIME
IF OBJECT_ID('Tempdb..#tab1') IS NOT NULL
BEGIN
DROP TABLE #tab1
END
SET #now = GETDATE()
SET #StartDate = GETDATE() - 30
SET #EndDate = GETDATE() - 2
SELECT Flow.Id ,
Flow.ComponentId ,
Frequency.Name AS frequencyName ,
CONVERT(DATE, Flow.MeasurementDate) AS [Measurement Date] ,
DATEPART(HOUR, Flow.MeasurementDate) AS [Measurement Hour] ,
COALESCE(LAG(DATEPART(HOUR, Flow.MeasurementDate)) OVER ( PARTITION BY CONVERT(DATE, MeasurementDate) ORDER BY DATEPART(HOUR,
MeasurementDate) ),
0) AS [Measurement Previous Hour]
INTO #tab1
FROM Data.dbo.Flow
INNER JOIN Data.dbo.Component ON Flow.ComponentId = Component.Id
INNER JOIN Data.dbo.Frequency ON Flow.Frequency = Frequency.Id
WHERE Flow.LoaderCode = 'TOT'
AND Flow.Frequency = '1'
AND ScheduledVolume IS NOT NULL
AND CONVERT(DATE, MeasurementDate) BETWEEN CONVERT(DATE, #StartDate)
AND CONVERT(DATE, #EndDate)
SELECT T.* ,
CASE WHEN ( T.[Measurement Hour] - T.[Measurement Previous Hour] ) > 1
THEN ( T.[Measurement Hour] - T.[Measurement Previous Hour] - 1 )
ELSE 0
END AS [Missing Hours]
FROM #tab1a AS T
WHERE ( T.[Measurement Hour] - T.[Measurement Previous Hour] ) > 1
I got a function in my database, that returns a table. What I'm trying to do is select joining a table and that function.
I saw that it can't be done in the FROM place, but if I put the function in the select it takes too long to execute.
My SQL is:
select
"Grades"."id",
SUPRIMENTO_LOJA("Grades"."id", 30, 1, 1)
from
"Grades"
This takes more than 500s to execute
I tried this too but it returns an error
select
*
from
"Grades",
SUPRIMENTO_LOJA("Grades"."id", 30, 1, 1)
Whats the best way to make this select to work?
EDIT:
The function is this:
CREATE OR REPLACE FUNCTION suprimento_loja(grade_id integer, vendas_dias integer, lojaId integer, embalagem numeric(15, 4))
RETURNS TABLE(qtd integer, maximo integer, ultFornecedor character varying(50),
ultCompra character varying(10), ultVenda character varying(10), classeLoja character varying(1),
vendas integer, sugestao integer, giroLoja numeric(15, 4))
AS $$
DECLARE
qtde1 integer;
vendasdiae1 integer;
maximoe1 integer;
ultvendae1 timestamp;
ultcomprae1 timestamp;
ultforne1 varchar(50);
classee1 varchar(1);
vendase1 integer;
qtde2 integer;
vendasdiae2 integer;
maximoe2 integer;
ultvendae2 timestamp;
ultcomprae2 timestamp;
ultforne2 varchar(50);
vendase2 integer;
qtde3 integer;
vendasdiae3 integer;
maximoe3 integer;
ultvendae3 timestamp;
ultcomprae3 timestamp;
ultforne3 varchar(50);
vendase3 integer;
giroe1 numeric(15, 4);
giroe2 numeric(15, 4);
giroe3 numeric(15, 4);
BEGIN
with vendas as (
select
sum(coalesce("quantidade", 0)) as vendas_periodo,
"inventario_id"
from
"WVItens"
where
"WVItens"."ultimoDownload" between current_timestamp - (select to_interval(vendas_dias))
and current_timestamp and coalesce("status", '') = ''
group by
"inventario_id")
select into qtde1, vendasdiae1, maximoe1, ultvendae1, ultcomprae1, ultforne1, classee1, vendase1, giroe1
cast("quantidadeAtual" as integer),
cast("vendasPorDia" as integer),
cast("maximoEmDias" as integer),
"dataUltimaVenda",
"dataUltimaCompra",
"ultimoFornecedor",
"classe",
cast(vendas_periodo as integer),
coalesce("giro", 0)
from
"Inventarios",
"Lojas",
vendas
where
"Inventarios"."estoque_id" = "Lojas"."estoque1_id" and
coalesce("Inventarios"."status", '') = '' and
"Inventarios"."id" = vendas."inventario_id" and
"Lojas"."id" = lojaId and
"grade_id" = gradeId;
with vendas as (
select
sum(coalesce("quantidade", 0)) as vendas_periodo,
"inventario_id"
from
"WVItens"
where
"WVItens"."ultimoDownload" between current_timestamp - (select to_interval(vendas_dias))
and current_timestamp and coalesce("status", '') = ''
group by
"inventario_id")
select into qtde2, vendasdiae2, maximoe2, ultvendae2, ultcomprae2, ultforne2, vendase2, giroe2
cast("quantidadeAtual" as integer),
cast("vendasPorDia" as integer),
cast("maximoEmDias" as integer),
"dataUltimaVenda",
"dataUltimaCompra",
"ultimoFornecedor",
cast(vendas_periodo as integer),
coalesce("giro", 0)
from
"Inventarios",
"Lojas",
vendas
where
"Inventarios"."estoque_id" = "Lojas"."estoque2_id" and
coalesce("Inventarios"."status", '') = '' and
"Inventarios"."id" = vendas."inventario_id" and
"Lojas"."id" = lojaId and
"grade_id" = gradeId;
with vendas as (
select
sum(coalesce("quantidade", 0)) as vendas_periodo,
"inventario_id"
from
"WVItens"
where
"WVItens"."ultimoDownload" between current_timestamp - (select to_interval(vendas_dias))
and current_timestamp and coalesce("status", '') = ''
group by
"inventario_id")
select into qtde3, vendasdiae3, maximoe3, ultvendae3, ultcomprae3, ultforne3, vendase3, giroe3
cast("quantidadeAtual" as integer),
cast("vendasPorDia" as integer),
cast("maximoEmDias" as integer),
"dataUltimaVenda",
"dataUltimaCompra",
"ultimoFornecedor",
cast(vendas_periodo as integer),
coalesce("giro", 0)
from
"Inventarios",
"Lojas",
vendas
where
"Inventarios"."estoque_id" = "Lojas"."estoque2_id" and
coalesce("Inventarios"."status", '') = '' and
"Inventarios"."id" = vendas."inventario_id" and
"Lojas"."id" = lojaId and
"grade_id" = gradeId;
qtd := 0;
IF (qtde1 is not null) THEN
qtd := qtd + qtde1;
END IF;
IF (qtde2 is not null) THEN
qtd := qtd + qtde2;
END IF;
IF (qtde3 is not null) THEN
qtd := qtd + qtde3;
END IF;
giroLoja = (giroe1 + giroe2 + giroe3) / 3;
maximo := 0;
IF ((maximoe1 is not null) and (vendasdiae1 is not null)) THEN
maximo := maximo + (maximoe1 * vendasdiae1);
END IF;
IF ((maximoe2 is not null) and (vendasdiae2 is not null)) THEN
maximo := maximo + (maximoe2 * vendasdiae2);
END IF;
IF ((maximoe3 is not null) and (vendasdiae3 is not null)) THEN
maximo := maximo + (maximoe3 * vendasdiae3);
END IF;
IF (qtde1 is null) THEN
qtde1 := 0;
END IF;
IF (qtde2 is null) THEN
qtde2 := 0;
END IF;
IF (qtde3 is null) THEN
qtde3 := 0;
END IF;
IF (maximoe1 is null) THEN
maximoe1 := 0;
END IF;
IF (maximoe2 is null) THEN
maximoe2 := 0;
END IF;
IF (maximoe3 is null) THEN
maximoe3 := 0;
END IF;
IF (vendasdiae1 is null) THEN
vendasdiae1 := 0;
END IF;
IF (vendasdiae2 is null) THEN
vendasdiae2 := 0;
END IF;
IF (vendasdiae3 is null) THEN
vendasdiae3 := 0;
END IF;
IF (vendase1 is null) THEN
vendase1 := 0;
END IF;
IF (vendase2 is null) THEN
vendase2 := 0;
END IF;
IF (vendase3 is null) THEN
vendase3 := 0;
END IF;
ultCompra := '';
ultVenda := '';
ultFornecedor := '';
IF (ultcomprae1 is null) THEN
IF (ultcomprae2 is null) THEN
IF (ultcomprae3 is not null) THEN
ultCompra := cast(extract(day from ultcomprae3) || '/' || extract(month from ultcomprae3) || '/' || extract(year from ultcomprae3) as varchar(10));
ultFornecedor := ultforne3;
END IF;
ELSE
IF ((ultcomprae3 is null) or (ultcomprae2 > ultcomprae3)) THEN
ultCompra := cast(extract(day from ultcomprae2) || '/' || extract(month from ultcomprae2) || '/' || extract(year from ultcomprae2) as varchar(10));
ultFornecedor := ultforne2;
ELSE
ultCompra := cast(extract(day from ultcomprae3) || '/' || extract(month from ultcomprae3) || '/' || extract(year from ultcomprae3) as varchar(10));
ultFornecedor := ultforne3;
END IF;
END IF;
ELSE
IF ((ultcomprae2 is null) or (ultcomprae1 > ultcomprae2)) THEN
IF ((ultcomprae3 is null) or (ultcomprae1 > ultcomprae3)) THEN
ultCompra := cast(extract(day from ultcomprae1) || '/' || extract(month from ultcomprae1) || '/' || extract(year from ultcomprae1) as varchar(10));
ultFornecedor := ultforne1;
ELSE
IF (ultcomprae3 is not null) THEN
ultCompra := cast(extract(day from ultcomprae3) || '/' || extract(month from ultcomprae3) || '/' || extract(year from ultcomprae3) as varchar(10));
ultFornecedor := ultforne3;
END IF;
END IF;
ELSE
IF ((ultcomprae3 is null) or (ultcomprae2 > ultcomprae3)) THEN
ultCompra := cast(extract(day from ultcomprae2) || '/' || extract(month from ultcomprae2) || '/' || extract(year from ultcomprae2) as varchar(10));
ultFornecedor := ultforne2;
ELSE
ultCompra := cast(extract(day from ultcomprae3) || '/' || extract(month from ultcomprae3) || '/' || extract(year from ultcomprae3) as varchar(10));
ultFornecedor := ultforne3;
END IF;
END IF;
END IF;
IF (ultvendae1 is null) THEN
IF (ultvendae2 is null) THEN
IF (ultvendae3 is not null) THEN
ultVenda := cast(extract(day from ultvendae3) || '/' || extract(month from ultvendae3) || '/' || extract(year from ultvendae3) as varchar(10));
END IF;
ELSE
IF ((ultvendae3 is null) or (ultvendae2 > ultvendae3)) THEN
ultVenda := cast(extract(day from ultvendae2) || '/' || extract(month from ultvendae2) || '/' || extract(year from ultvendae2) as varchar(10));
ELSE
ultVenda := cast(extract(day from ultvendae3) || '/' || extract(month from ultvendae3) || '/' || extract(year from ultvendae3) as varchar(10));
END IF;
END IF;
ELSE
IF ((ultvendae2 is null) or (ultvendae1 > ultvendae2)) THEN
IF ((ultvendae3 is null) or (ultvendae1 > ultvendae3)) THEN
ultVenda := cast(extract(day from ultvendae1) || '/' || extract(month from ultvendae1) || '/' || extract(year from ultvendae1) as varchar(10));
ELSE
IF (ultvendae3 is not null) THEN
ultVenda := cast(extract(day from ultvendae3) || '/' || extract(month from ultvendae3) || '/' || extract(year from ultvendae3) as varchar(10));
END IF;
END IF;
ELSE
IF ((ultvendae3 is null) or (ultvendae2 > ultvendae3)) THEN
ultVenda := cast(extract(day from ultvendae2) || '/' || extract(month from ultvendae2) || '/' || extract(year from ultvendae2) as varchar(10));
ELSE
ultVenda := cast(extract(day from ultvendae3) || '/' || extract(month from ultvendae3) || '/' || extract(year from ultvendae3) as varchar(10));
END IF;
END IF;
END IF;
vendas = vendase1 + vendase2 + vendase3;
classeLoja := classee1;
IF ((qtde1 + qtde2 + qtde3) > ((maximoe1 * vendasdiae1) + (maximoe2 * vendasdiae2) + (maximoe3 * vendasdiae3))) THEN
sugestao := 0;
ELSE
sugestao := cast(((((maximoe1 * vendasdiae1) + (maximoe2 * vendasdiae2) + (maximoe3 * vendasdiae3)) - (qtde1 + qtde2 + qtde3)) + 0.4) as integer);
END IF;
RETURN NEXT;
END
$$ LANGUAGE plpgsql;
I tried with some query but it got too long, and it isnt even the final query that I need
with suprimento as (
with vendas as (
select
sum(coalesce("quantidade", 0)) as vendas_periodo,
"inventario_id"
from
"WVItens"
where
"WVItens"."ultimoDownload" between current_timestamp - (select to_interval(30))
and current_timestamp and coalesce("status", '') = ''
group by
"inventario_id")
select
"grade_id",
"estoque_id",
sum(cast("quantidadeAtual" as integer)) as "quantidade",
sum(cast("vendasPorDia" as integer)) as "vendasPorDia",
sum(cast("maximoEmDias" as integer)) as "maximoEmDias",
max("dataUltimaVenda") as "ultVenda",
max("dataUltimaCompra") as "ultCompra",
max("ultimoFornecedor") as "ultFornecedor",
sum(cast(vendas_periodo as integer)) as "vendasPeriodo",
max(coalesce("giro", 0)) as "giro"
from
"Inventarios"
left outer join vendas on ("Inventarios"."id" = vendas."inventario_id")
where
coalesce("Inventarios"."status", '') = ''
group by
"grade_id", "estoque_id")
NEW EDIT!!!
I tried to make one query only but it is runing until now (passed 800seconds), the query is:
WITH suprimento_loja as (
WITH suprimento as (
WITH vendas as (
SELECT "inventario_id"
, SUM(coalesce("quantidade", 0)) as vendas_periodo
FROM "WVItens" vwi
WHERE vwi."ultimoDownload" between current_timestamp - (SELECT to_interval(30))
AND current_timestamp
AND coalesce("status", '') = ''
GROUP BY "inventario_id"
)
SELECT
"estoque_id",
"grade_id",
"classe" as classe
, cast("quantidadeAtual" as integer) as qtd
, cast("vendasPorDia" as integer) as vendasDia
, cast("maximoEmDias" as integer) as maximo
, coalesce("dataUltimaVenda", timestamp'01.01.1980') as ultVenda
, "dataUltimaCompra" as ultCompra
, "ultimoFornecedor" as ultForn
, cast(vendas_periodo as integer) as vendas_periodo
, coalesce("giro", 0) as giro
FROM "Inventarios" inv
LEFT OUTER JOIN vendas ve ON inv."id" = ve."inventario_id"
)
select
lo."id" as id,
e1."grade_id" as grade_id,
e1.ultVenda,
case
when e1.ultVenda > coalesce(e2.ultVenda, timestamp'01.01.1980') and e1.ultVenda > coalesce(e3.ultVenda, timestamp'01.01.1980')
then e1.ultVenda
else
case
when coalesce(e2.ultVenda, timestamp'01.01.1980') > coalesce(e3.ultVenda, timestamp'01.01.1980')
then e2.ultVenda
else e3.ultVenda
end
end as ultVenda,
case
when e1.ultCompra > coalesce(e2.ultCompra, timestamp'01.01.1980') and e1.ultCompra > coalesce(e3.ultCompra, timestamp'01.01.1980')
then e1.ultCompra
else
case
when coalesce(e2.ultCompra, timestamp'01.01.1980') > coalesce(e3.ultCompra, timestamp'01.01.1980')
then e2.ultCompra
else e3.ultCompra
end
end as ultCompra,
case
when e1.ultCompra > coalesce(e2.ultCompra, timestamp'01.01.1980') and e1.ultCompra > coalesce(e3.ultCompra, timestamp'01.01.1980')
then e1.ultForn
else
case
when coalesce(e2.ultCompra, timestamp'01.01.1980') > coalesce(e3.ultCompra, timestamp'01.01.1980')
then e2.ultForn
else e3.ultForn
end
end as ultForn,
coalesce(e1.vendas_periodo, 0) + coalesce(e2.vendas_periodo, 0) + coalesce(e3.vendas_periodo, 0) as vendas_periodo,
e1.classe,
(coalesce(e1.maximo, 0) * coalesce(e1.vendasDia, 0)) + (coalesce(e2.maximo, 0) * coalesce(e2.vendasDia, 0)) + (coalesce(e3.maximo, 0) * coalesce(e3.vendasDia, 0)) as maximo,
coalesce(e1.giro, 0) as giro,
coalesce(e1.qtd, 0) + coalesce(e2.qtd, 0) + coalesce(e3.qtd, 0) as qtde,
case
when coalesce(e1.giro, 0) = 0
then 0
else
case
when ((coalesce(e1.qtd, 0) + coalesce(e2.qtd, 0) + coalesce(e3.qtd, 0)) > ((coalesce(e1.maximo, 0) * coalesce(e1.vendasDia, 0)) + (coalesce(e2.maximo, 0) * coalesce(e2.vendasDia, 0)) + (coalesce(e3.maximo, 0) * coalesce(e3.vendasDia, 0))))
then 0
else cast(((((coalesce(e1.maximo, 0) * coalesce(e1.vendasDia, 0)) + (coalesce(e2.maximo, 0) * coalesce(e2.vendasDia, 0)) + (coalesce(e3.maximo, 0) * coalesce(e3.vendasDia, 0)))
- (coalesce(e1.qtd, 0) + coalesce(e2.qtd, 0) + coalesce(e3.qtd, 0))) + 0.4) as integer)
end
end as sugestao
from
"Lojas" lo
LEFT OUTER JOIN suprimento e2 ON e2."estoque_id" = lo."estoque2_id"
LEFT OUTER JOIN suprimento e3 ON e3."estoque_id" = lo."estoque3_id"
JOIN suprimento e1 ON e1."estoque_id" = lo."estoque1_id")
SELECT
gr."id",
sl1.*,
sl2.*,
sl3.*,
sl4.*,
sl5.*,
sl6.*
FROM
"Grades" gr
JOIN suprimento_loja sl1 ON sl1."grade_id" = gr."id"
JOIN suprimento_loja sl2 ON sl2."grade_id" = gr."id"
JOIN suprimento_loja sl3 ON sl3."grade_id" = gr."id"
JOIN suprimento_loja sl4 ON sl4."grade_id" = gr."id"
JOIN suprimento_loja sl5 ON sl5."grade_id" = gr."id"
JOIN suprimento_loja sl6 ON sl6."grade_id" = gr."id"
WHERE
sl1."id" = 1 AND
sl2."id" = 2 AND
sl3."id" = 3 AND
sl4."id" = 4 AND
sl5."id" = 5 AND
sl6."id" = 6
I used aliases and join so you can read easly
I got it working but in other way.
If someone got some similar problem the solution I got is this:
SELECT
gr.id,
max(CASE sl.id WHEN 1 THEN sl.ultVenda ELSE timestamp'01.01.1980' END) AS ultVenda_l1,
max(CASE sl.id WHEN 2 THEN sl.ultVenda ELSE timestamp'01.01.1980' END) AS ultVenda_l2,
max(CASE sl.id WHEN 3 THEN sl.ultVenda ELSE timestamp'01.01.1980' END) AS ultVenda_l3,
max(CASE sl.id WHEN 4 THEN sl.ultVenda ELSE timestamp'01.01.1980' END) AS ultVenda_l4,
max(CASE sl.id WHEN 5 THEN sl.ultVenda ELSE timestamp'01.01.1980' END) AS ultVenda_l5,
max(CASE sl.id WHEN 6 THEN sl.ultVenda ELSE timestamp'01.01.1980' END) AS ultVenda_l6,
max(CASE sl.id WHEN 1 THEN sl.ultCompra ELSE timestamp'01.01.1980' END) AS ultCompra_l1,
max(CASE sl.id WHEN 2 THEN sl.ultCompra ELSE timestamp'01.01.1980' END) AS ultCompra_l2,
max(CASE sl.id WHEN 3 THEN sl.ultCompra ELSE timestamp'01.01.1980' END) AS ultCompra_l3,
max(CASE sl.id WHEN 4 THEN sl.ultCompra ELSE timestamp'01.01.1980' END) AS ultCompra_l4,
max(CASE sl.id WHEN 5 THEN sl.ultCompra ELSE timestamp'01.01.1980' END) AS ultCompra_l5,
max(CASE sl.id WHEN 6 THEN sl.ultCompra ELSE timestamp'01.01.1980' END) AS ultCompra_l6,
max(CASE sl.id WHEN 1 THEN sl.ultForn ELSE '' END) AS ultForn_l1,
max(CASE sl.id WHEN 2 THEN sl.ultForn ELSE '' END) AS ultForn_l2,
max(CASE sl.id WHEN 3 THEN sl.ultForn ELSE '' END) AS ultForn_l3,
max(CASE sl.id WHEN 4 THEN sl.ultForn ELSE '' END) AS ultForn_l4,
max(CASE sl.id WHEN 5 THEN sl.ultForn ELSE '' END) AS ultForn_l5,
max(CASE sl.id WHEN 6 THEN sl.ultForn ELSE '' END) AS ultForn_l6,
max(CASE sl.id WHEN 1 THEN sl.vendas_periodo ELSE 0 END) AS vendas_periodo_l1,
max(CASE sl.id WHEN 2 THEN sl.vendas_periodo ELSE 0 END) AS vendas_periodo_l2,
max(CASE sl.id WHEN 3 THEN sl.vendas_periodo ELSE 0 END) AS vendas_periodo_l3,
max(CASE sl.id WHEN 4 THEN sl.vendas_periodo ELSE 0 END) AS vendas_periodo_l4,
max(CASE sl.id WHEN 5 THEN sl.vendas_periodo ELSE 0 END) AS vendas_periodo_l5,
max(CASE sl.id WHEN 6 THEN sl.vendas_periodo ELSE 0 END) AS vendas_periodo_l6,
max(CASE sl.id WHEN 1 THEN sl.maximo ELSE 0 END) AS maximo_l1,
max(CASE sl.id WHEN 2 THEN sl.maximo ELSE 0 END) AS maximo_l2,
max(CASE sl.id WHEN 3 THEN sl.maximo ELSE 0 END) AS maximo_l3,
max(CASE sl.id WHEN 4 THEN sl.maximo ELSE 0 END) AS maximo_l4,
max(CASE sl.id WHEN 5 THEN sl.maximo ELSE 0 END) AS maximo_l5,
max(CASE sl.id WHEN 6 THEN sl.maximo ELSE 0 END) AS maximo_l6,
max(CASE sl.id WHEN 1 THEN sl.giro ELSE 0 END) AS giro_l1,
max(CASE sl.id WHEN 2 THEN sl.giro ELSE 0 END) AS giro_l2,
max(CASE sl.id WHEN 3 THEN sl.giro ELSE 0 END) AS giro_l3,
max(CASE sl.id WHEN 4 THEN sl.giro ELSE 0 END) AS giro_l4,
max(CASE sl.id WHEN 5 THEN sl.giro ELSE 0 END) AS giro_l5,
max(CASE sl.id WHEN 6 THEN sl.giro ELSE 0 END) AS giro_l6,
max(CASE sl.id WHEN 1 THEN sl.qtde ELSE 0 END) AS qtd_l1,
max(CASE sl.id WHEN 2 THEN sl.qtde ELSE 0 END) AS qtd_l2,
max(CASE sl.id WHEN 3 THEN sl.qtde ELSE 0 END) AS qtd_l3,
max(CASE sl.id WHEN 4 THEN sl.qtde ELSE 0 END) AS qtd_l4,
max(CASE sl.id WHEN 5 THEN sl.qtde ELSE 0 END) AS qtd_l5,
max(CASE sl.id WHEN 6 THEN sl.qtde ELSE 0 END) AS qtd_l6,
max(CASE sl.id WHEN 1 THEN sl.sugestao ELSE 0 END) AS sugestao_l1,
max(CASE sl.id WHEN 2 THEN sl.sugestao ELSE 0 END) AS sugestao_l2,
max(CASE sl.id WHEN 3 THEN sl.sugestao ELSE 0 END) AS sugestao_l3,
max(CASE sl.id WHEN 4 THEN sl.sugestao ELSE 0 END) AS sugestao_l4,
max(CASE sl.id WHEN 5 THEN sl.sugestao ELSE 0 END) AS sugestao_l5,
max(CASE sl.id WHEN 6 THEN sl.sugestao ELSE 0 END) AS sugestao_l6
FROM "Grades" gr
INNER JOIN suprimento_loja sl ON sl.grade_id = gr.id
group by gr.id
order by gr.id
And the view 'suprimento_loja' is that query used before in the function.
The only thing you can do now to speed up the query - remake the function to take less time.
It PostgreSQL 9.3 you will be able to use your second query variant with LATERAL, but it wont be significantly faster.
This is only the edited body (untested, hope I didn't make any typos ;-):
WITH vendas as (
SELECT "inventario_id"
, SUM(coalesce("quantidade", 0)) as vendas_periodo
FROM "WVItens" vwi
WHERE vwi."ultimoDownload" between current_timestamp - (SELECT to_interval(vendas_dias)) AND current_timestamp
AND coalesce("status", '') = ''
GROUP BY "inventario_id"
)
SELECT into qtde1, vendasdiae1, maximoe1, ultvendae1, ultcomprae1, ultforne1, classee1, vendase1, giroe1
cast("quantidadeAtual" as integer)
, cast("vendasPorDia" as integer)
, cast("maximoEmDias" as integer)
, "dataUltimaVenda"
, "dataUltimaCompra"
, "ultimoFornecedor"
, "classe"
, cast(vendas_periodo as integer)
, coalesce("giro", 0)
FROM "Inventarios" inv
JOIN "Lojas" lo ON inv."estoque_id" = lo."estoque1_id"
JOIN vendas ve ON inv."id" = ve."inventario_id"
WHERE coalesce( inv."status", '') = ''
AND lo."id" = lojaId
AND "grade_id" = gradeId
;
WITH vendas as (
SELECT "inventario_id"
, SUM(coalesce("quantidade", 0)) as vendas_periodo
FROM "WVItens" vwi
WHERE vwi."ultimoDownload" between current_timestamp - (SELECT to_interval(vendas_dias))
AND current_timestamp
AND coalesce("status", '') = ''
GROUP BY "inventario_id"
)
SELECT into qtde2, vendasdiae2, maximoe2, ultvendae2, ultcomprae2, ultforne2, vendase2, giroe2
cast("quantidadeAtual" as integer)
, cast("vendasPorDia" as integer)
, cast("maximoEmDias" as integer)
, "dataUltimaVenda"
, "dataUltimaCompra"
, "ultimoFornecedor"
, cast(vendas_periodo as integer)
, coalesce("giro", 0)
FROM "Inventarios" inv
JOIN "Lojas" lo ON inv."estoque_id" = lo."estoque2_id"
JOIN vendas ve ON inv."id" = vendas."inventario_id"
WHERE coalesce( inv."status", '') = ''
AND lo."id" = lojaId
AND "grade_id" = gradeId
;
WITH vendas as (
SELECT "inventario_id"
, SUM(coalesce("quantidade", 0)) as vendas_periodo
FROM "WVItens" vwi
WHERE vwi."ultimoDownload" between current_timestamp - (SELECT to_interval(vendas_dias))
AND current_timestamp
AND coalesce("status", '') = ''
GROUP BY "inventario_id"
)
SELECT into qtde3, vendasdiae3, maximoe3, ultvendae3, ultcomprae3, ultforne3, vendase3, giroe3
cast("quantidadeAtual" as integer)
, cast("vendasPorDia" as integer)
, cast("maximoEmDias" as integer)
, "dataUltimaVenda"
, "dataUltimaCompra"
, "ultimoFornecedor"
, cast(vendas_periodo as integer)
, coalesce("giro", 0)
FROM "Inventarios" inv
JOIN "Lojas" lo ON inv."estoque_id" = lo."estoque2_id"
JOIN vendas ve ON inv."id" = vendas."inventario_id"
WHERE coalesce( inv."status", '') = ''
AND lo."id" = lojaId
AND "grade_id" = gradeId
;
At first glance, It appears you are doing exactly the same query three times, with different constants, which to me looks subobtimate.
I'm working on a Windows desktop application written in C# 4.0 with a SQL Server 2005 backend. The application uses a Timestamp datatype field to handle data concurrency. Everything was working fine until I put some Triggers on the data tables to handle auditting. Now I am getting false data concurrency errors when I run my test scripts. It's as if the triggers are updating the Timestamp field that I am using to manage concurrency.
Does that sound right? And if so, is there anything I can do about it?
In case you need more information here is a brief description of how the concurrency checking works. When a record is loaded, it reads the Timestamp datatype value and stores it in the class along with all the other data.
When the user attempts to save the data, the class begins a transaction, reads the record from the database and compares the Timestamp fields.
If they match it goes ahead with the save in the same transaction, and grabs the new Timestamp with and T-SQL statement that lookds like "UPDATE ... ; SELECT ##DBTS".
If the Timestamps don't match it throws a data concurrency exception.
It was working as planned before I added the audit triggers, but now it always throws a data concurrency exception if a record is updated and then updated again. My guess is that it is getting the new timestamp value after the update, but the trigger causes it to change again after that.
Here is the code that performs the update:
// Begin Transaction
SqlConnection conn = new SqlConnection(DataGateway.ConnStr);
SqlTransaction trans;
conn.Open();
trans = conn.BeginTransaction();
// Read current record
DataTable dt = base.Select(conn, trans);
// Timestamps match?
DataRow row = dt.Rows[0];
if (RowversionsEqual(Rowversion, (byte[])row["Rowversion"])) // Rowversion is a class property that holds the Timestamp obtained when data is initially read, Rowversions equal is a function that compares two Timestamp values
{
// Timestamps match, update record
SqlCommand cmd = new SqlCommand("UPDATE WrdImp SET Imp = #Imp, Note = #Note, EditDate = #EditTimestamp, EditBy = #EditBy WHERE BID = #BID AND WID = #WID; SELECT ##DBTS", conn, trans);
// Code to insert parameter values
Rowversion = (byte[])cmd.ExecuteScalar();
trans.Commit();
}
else
{
// Another user has made an interim change, notify user
trans.Rollback();
conn.Close();
throw new ImpDataConcurrencyException(dt.Rows[0]["EditBy"].ToString(), (DateTime)dt.Rows[0]["EditDate"],MsgComponent.Title, dt.Rows[0]["Imp"].ToString(), dt.Rows[0]["Note"].ToString());
}
Here is one of the update triggers. It was auto-generated by a third party product called APEX SQL Audit.
ALTER TRIGGER [dbo].[tr_u_AUDIT_WrdImp]
ON [dbo].[WrdImp]
FOR UPDATE
NOT FOR REPLICATION
As
BEGIN
DECLARE
#IDENTITY_SAVE varchar(50),
#AUDIT_LOG_TRANSACTION_ID Int,
#PRIM_KEY nvarchar(4000),
#Inserted bit,
--#TABLE_NAME nvarchar(4000),
#ROWS_COUNT int
SET NOCOUNT ON
--Set #TABLE_NAME = '[dbo].[WrdImp]'
Select #ROWS_COUNT=count(*) from inserted
SET #IDENTITY_SAVE = CAST(IsNull(##IDENTITY,1) AS varchar(50))
INSERT
INTO [PLIMS].dbo.AUDIT_LOG_TRANSACTIONS
(
TABLE_NAME,
TABLE_SCHEMA,
AUDIT_ACTION_ID,
HOST_NAME,
APP_NAME,
MODIFIED_BY,
MODIFIED_DATE,
AFFECTED_ROWS,
[DATABASE]
)
values(
'WrdImp',
'dbo',
1, -- ACTION ID For UPDATE
CASE
WHEN LEN(HOST_NAME()) < 1 THEN ' '
ELSE HOST_NAME()
END,
CASE
WHEN LEN(APP_NAME()) < 1 THEN ' '
ELSE APP_NAME()
END,
SUSER_SNAME(),
GETDATE(),
#ROWS_COUNT,
'PLIMS'
)
Set #AUDIT_LOG_TRANSACTION_ID = SCOPE_IDENTITY()
SET #Inserted = 0
If UPDATE([Imp])
BEGIN
INSERT
INTO [PLIMS].dbo.AUDIT_LOG_DATA
(
AUDIT_LOG_TRANSACTION_ID,
PRIMARY_KEY_DATA,
COL_NAME,
OLD_VALUE_LONG,
NEW_VALUE_LONG,
DATA_TYPE
, KEY1, KEY2
)
SELECT
#AUDIT_LOG_TRANSACTION_ID,
convert(nvarchar(1500), IsNull('[WID]='+CONVERT(nvarchar(4000), IsNull(OLD.[WID], NEW.[WID]), 0), '[WID] Is Null')+' AND '+IsNull('[BID]='+CONVERT(nvarchar(4000), IsNull(OLD.[BID], NEW.[BID]), 0), '[BID] Is Null')),
'Imp',
CONVERT(nvarchar(4000), OLD.[Imp], 0),
CONVERT(nvarchar(4000), NEW.[Imp], 0),
'A'
, IsNULL( CONVERT(nvarchar(500), CONVERT(nvarchar(4000), OLD.[WID], 0)), CONVERT(nvarchar(500), CONVERT(nvarchar(4000), NEW.[WID], 0))), IsNULL( CONVERT(nvarchar(500), CONVERT(nvarchar(4000), OLD.[BID], 0)), CONVERT(nvarchar(500), CONVERT(nvarchar(4000), NEW.[BID], 0)))
FROM deleted OLD Inner Join inserted NEW On
(CONVERT(nvarchar(4000), NEW.[WID], 0)=CONVERT(nvarchar(4000), OLD.[WID], 0) or (NEW.[WID] Is Null and OLD.[WID] Is Null)) AND (CONVERT(nvarchar(4000), NEW.[BID], 0)=CONVERT(nvarchar(4000), OLD.[BID], 0) or (NEW.[BID] Is Null and OLD.[BID] Is Null))
where (
(
NEW.[Imp] <>
OLD.[Imp]
) Or
(
NEW.[Imp] Is Null And
OLD.[Imp] Is Not Null
) Or
(
NEW.[Imp] Is Not Null And
OLD.[Imp] Is Null
)
)
SET #Inserted = CASE WHEN ##ROWCOUNT > 0 Then 1 Else #Inserted End
END
If UPDATE([Note])
BEGIN
INSERT
INTO [PLIMS].dbo.AUDIT_LOG_DATA
(
AUDIT_LOG_TRANSACTION_ID,
PRIMARY_KEY_DATA,
COL_NAME,
OLD_VALUE_LONG,
NEW_VALUE_LONG,
DATA_TYPE
, KEY1, KEY2
)
SELECT
#AUDIT_LOG_TRANSACTION_ID,
convert(nvarchar(1500), IsNull('[WID]='+CONVERT(nvarchar(4000), IsNull(OLD.[WID], NEW.[WID]), 0), '[WID] Is Null')+' AND '+IsNull('[BID]='+CONVERT(nvarchar(4000), IsNull(OLD.[BID], NEW.[BID]), 0), '[BID] Is Null')),
'Note',
CONVERT(nvarchar(4000), OLD.[Note], 0),
CONVERT(nvarchar(4000), NEW.[Note], 0),
'A'
, IsNULL( CONVERT(nvarchar(500), CONVERT(nvarchar(4000), OLD.[WID], 0)), CONVERT(nvarchar(500), CONVERT(nvarchar(4000), NEW.[WID], 0))), IsNULL( CONVERT(nvarchar(500), CONVERT(nvarchar(4000), OLD.[BID], 0)), CONVERT(nvarchar(500), CONVERT(nvarchar(4000), NEW.[BID], 0)))
FROM deleted OLD Inner Join inserted NEW On
(CONVERT(nvarchar(4000), NEW.[WID], 0)=CONVERT(nvarchar(4000), OLD.[WID], 0) or (NEW.[WID] Is Null and OLD.[WID] Is Null)) AND (CONVERT(nvarchar(4000), NEW.[BID], 0)=CONVERT(nvarchar(4000), OLD.[BID], 0) or (NEW.[BID] Is Null and OLD.[BID] Is Null))
where (
(
NEW.[Note] <>
OLD.[Note]
) Or
(
NEW.[Note] Is Null And
OLD.[Note] Is Not Null
) Or
(
NEW.[Note] Is Not Null And
OLD.[Note] Is Null
)
)
SET #Inserted = CASE WHEN ##ROWCOUNT > 0 Then 1 Else #Inserted End
END
If UPDATE([EditDate])
BEGIN
INSERT
INTO [PLIMS].dbo.AUDIT_LOG_DATA
(
AUDIT_LOG_TRANSACTION_ID,
PRIMARY_KEY_DATA,
COL_NAME,
OLD_VALUE_LONG,
NEW_VALUE_LONG,
DATA_TYPE
, KEY1, KEY2
)
SELECT
#AUDIT_LOG_TRANSACTION_ID,
convert(nvarchar(1500), IsNull('[WID]='+CONVERT(nvarchar(4000), IsNull(OLD.[WID], NEW.[WID]), 0), '[WID] Is Null')+' AND '+IsNull('[BID]='+CONVERT(nvarchar(4000), IsNull(OLD.[BID], NEW.[BID]), 0), '[BID] Is Null')),
'EditDate',
CONVERT(nvarchar(4000), OLD.[EditDate], 121),
CONVERT(nvarchar(4000), NEW.[EditDate], 121),
'A'
, IsNULL( CONVERT(nvarchar(500), CONVERT(nvarchar(4000), OLD.[WID], 0)), CONVERT(nvarchar(500), CONVERT(nvarchar(4000), NEW.[WID], 0))), IsNULL( CONVERT(nvarchar(500), CONVERT(nvarchar(4000), OLD.[BID], 0)), CONVERT(nvarchar(500), CONVERT(nvarchar(4000), NEW.[BID], 0)))
FROM deleted OLD Inner Join inserted NEW On
(CONVERT(nvarchar(4000), NEW.[WID], 0)=CONVERT(nvarchar(4000), OLD.[WID], 0) or (NEW.[WID] Is Null and OLD.[WID] Is Null)) AND (CONVERT(nvarchar(4000), NEW.[BID], 0)=CONVERT(nvarchar(4000), OLD.[BID], 0) or (NEW.[BID] Is Null and OLD.[BID] Is Null))
where (
(
NEW.[EditDate] <>
OLD.[EditDate]
) Or
(
NEW.[EditDate] Is Null And
OLD.[EditDate] Is Not Null
) Or
(
NEW.[EditDate] Is Not Null And
OLD.[EditDate] Is Null
)
)
SET #Inserted = CASE WHEN ##ROWCOUNT > 0 Then 1 Else #Inserted End
END
If UPDATE([EditBy])
BEGIN
INSERT
INTO [PLIMS].dbo.AUDIT_LOG_DATA
(
AUDIT_LOG_TRANSACTION_ID,
PRIMARY_KEY_DATA,
COL_NAME,
OLD_VALUE_LONG,
NEW_VALUE_LONG,
DATA_TYPE
, KEY1, KEY2
)
SELECT
#AUDIT_LOG_TRANSACTION_ID,
convert(nvarchar(1500), IsNull('[WID]='+CONVERT(nvarchar(4000), IsNull(OLD.[WID], NEW.[WID]), 0), '[WID] Is Null')+' AND '+IsNull('[BID]='+CONVERT(nvarchar(4000), IsNull(OLD.[BID], NEW.[BID]), 0), '[BID] Is Null')),
'EditBy',
CONVERT(nvarchar(4000), OLD.[EditBy], 0),
CONVERT(nvarchar(4000), NEW.[EditBy], 0),
'A'
, IsNULL( CONVERT(nvarchar(500), CONVERT(nvarchar(4000), OLD.[WID], 0)), CONVERT(nvarchar(500), CONVERT(nvarchar(4000), NEW.[WID], 0))), IsNULL( CONVERT(nvarchar(500), CONVERT(nvarchar(4000), OLD.[BID], 0)), CONVERT(nvarchar(500), CONVERT(nvarchar(4000), NEW.[BID], 0)))
FROM deleted OLD Inner Join inserted NEW On
(CONVERT(nvarchar(4000), NEW.[WID], 0)=CONVERT(nvarchar(4000), OLD.[WID], 0) or (NEW.[WID] Is Null and OLD.[WID] Is Null)) AND (CONVERT(nvarchar(4000), NEW.[BID], 0)=CONVERT(nvarchar(4000), OLD.[BID], 0) or (NEW.[BID] Is Null and OLD.[BID] Is Null))
where (
(
NEW.[EditBy] <>
OLD.[EditBy]
) Or
(
NEW.[EditBy] Is Null And
OLD.[EditBy] Is Not Null
) Or
(
NEW.[EditBy] Is Not Null And
OLD.[EditBy] Is Null
)
)
SET #Inserted = CASE WHEN ##ROWCOUNT > 0 Then 1 Else #Inserted End
END
-- Watch
-- Lookup
IF #Inserted = 0
BEGIN
DELETE FROM [PLIMS].dbo.AUDIT_LOG_TRANSACTIONS WHERE AUDIT_LOG_TRANSACTION_ID = #AUDIT_LOG_TRANSACTION_ID
END
-- Restore ##IDENTITY Value
DECLARE #maxprec AS varchar(2)
SET #maxprec=CAST(##MAX_PRECISION as varchar(2))
EXEC('SELECT IDENTITY(decimal('+#maxprec+',0),'+#IDENTITY_SAVE+',1) id INTO #tmp')
End
GO
EXEC sp_settriggerorder #triggername=N'[dbo].[tr_u_AUDIT_WrdImp]', #order=N'Last', #stmttype=N'UPDATE'
##DBTS gives you the most recent rowversion value from the entire database - so yes, if any part of the trigger touches another table that also has a rowversion column, then you'll get a different answer.
Could you change your UPDATE to use an OUTPUT clause?
A single statement like:
UPDATE WrdImp
SET
Imp = #Imp,
Note = #Note,
EditDate = #EditTimestamp,
EditBy = #EditBy
OUTPUT
inserted.rowversion
WHERE
BID = #BID AND
WID = #WID AND
rowversion = #OldRowVersion;
Where I've added the old rowversion value (so SQL can do the check and we don't need to open an explicit transaction, nor need RowversionsEqual), and am returning the new rowversion value.
So you execute the above statement, and either: a) zero rows are returned - this means that something else updated this row, or b) one row is returned (assuming the rest of the WHERE clause is correctly limiting the UPDATE to one row), and it's guaranteed to contain the value of the rowversion column in that row, as it was when the UPDATE completed.
I'd forgotten the restriction re: output clause and triggers. I don't have a 2005 instance handy at the moment, but something like:
DECLARE #RV table (RV binary(8));
UPDATE WrdImp
SET
Imp = #Imp,
Note = #Note,
EditDate = #EditTimestamp,
EditBy = #EditBy
OUTPUT
inserted.rowversion INTO #RV(RV)
WHERE
BID = #BID AND
WID = #WID AND
rowversion = #OldRowVersion;
SELECT RV from #RV;
Which is now 3 statements rather than 1, but still ensures you're capturing the rowversion value from the row of interest, rather than the most recent value anywhere in the database.
I am trying to develop a T-SQL query which will do the following:
ROUND(100 * A / B, 1)
Simple in concept, but it's tricky because of possible B=0 denominator and also because of A and B variables. What I expect is a percent value like 93.2 (given in this format without %). Or even 932 would be acceptable since I could convert it later.
But instead, I'm currently getting 151, which is the number of records.
A = CASE WHEN A.MFG IS NULL AND A.MFG2 IS NULL AND A.QC IS NULL AND A.QC2 IS NULL THEN 1 ELSE 0 END
B = CASE WHEN [Date_Completed] IS NOT NULL THEN 1 ELSE 0 END
My current logic only divides A/B if B is not equal to zero. Can you please help me fix this? p.s. all fields above are from the same table A.
I tried:
SELECT CASE WHEN t.VarB<>0 THEN ROUND(100 * t.VarA / t.VarB, 1)
ELSE 0 /* or whatever you'd want to return in this case */
END
FROM (SELECT CASE WHEN A.MFG IS NULL AND A.MFG2 IS NULL AND A.QC IS NULL AND A.QC2 IS NULL THEN 1
ELSE 0
END AS VarA,
CASE WHEN [Date_Completed] IS NOT NULL THEN 1
ELSE 0
END AS VarB
FROM EXCEL.Batch_Records A) t
But I got 33000 rows returned instead of just one, where each row = 100 or 0.
Good idea, Conrad! I tested your solution and it works if I just want that one value. But what I didn't tell you was that there are additional values I need returned from same query. When I tried adding in the other value calculations, I got syntax errors. So here is my current query. How should htis be rewritten please?
select
SUM(CASE WHEN A.DATE_RECEIVED IS NOT NULL THEN 1 ELSE 0 END) AS NUM_RECEIVED,
SUM(CASE WHEN [Date_Completed] IS NOT NULL THEN 1 ELSE 0 END) AS NUM_COMPLETE_OF_OPENED,
SUM(CASE WHEN A.DATE_COMPLETED IS NOT NULL THEN 1 ELSE 0 END) AS NUM_COMPLETED_IN_MONTH,
SUM(CASE WHEN A.MFG IS NULL AND A.MFG2 IS NULL AND A.QC IS NULL AND A.QC2 IS NULL THEN 1 ELSE 0 END) AS NUM_WITHOUT_ERROR,
round(100 * a/b , 1)
from
(select
sum(CASE
WHEN A.MFG IS NULL AND A.MFG2 IS NULL AND A.QC IS NULL AND A.QC2 IS NULL THEN
1.0
ELSE 0.0 END) A,
sum(CASE WHEN [Date_Completed] IS NOT NULL THEN
1.0 ELSE 0.0 END) B
FROM EXCEL.Batch_Records a
LEFT JOIN EXCEL.QC_CODES d ON a.Part_Number = d.CODE_ID
WHERE (a.[Group] = #GROUP or #GROUP = '' OR #GROUP IS NULL) AND A.Date_Received >= #STARTDATE AND A.Date_Received <= #ENDDATE
Conrad correctly advised me that #TEMP1 was an empty table. But now I populated it and successfully designed this query with his help:
SET #STARTDATE = '1/1/11'
SET #ENDDATE = '1/31/11'
SET #GROUP = 'INTERMEDIATES_FISH'
--SET #TABLE_TITLE = 'BATCH RECORD SUCCESS RATE'
--SET #DEPT = 'QC'
IF EXISTS(SELECT * FROM TEMPDB.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '#TEMP1%')
DROP TABLE #TEMP1
--CREATE TABLE #TEMP1 ( MFG int , MFG2 int , QC int, QC2 INT , [Group] NVARCHAR(MAX), [Date_Completed] datetime, Date_Received datetime)
SELECT
MFG, MFG2, QC, QC2, [GROUP], [DATE_COMPLETED], [DATE_RECEIVED]
INTO #TEMP1
FROM EXCEL.Batch_Records a
WHERE (a.[Group] = #GROUP or #GROUP = '' OR #GROUP IS NULL) AND A.Date_Received >= #STARTDATE AND A.Date_Received <= #ENDDATE
------------------------------------------
;WITH CTE AS
(
SELECT
CASE
WHEN A.MFG IS NULL AND A.MFG2 IS NULL AND A.QC IS NULL AND A.QC2 IS NULL THEN
1.0
ELSE 0.0 END A,
CASE WHEN [Date_Completed] IS NOT NULL THEN 1.0 ELSE 0.0 END B,
CASE WHEN A.Date_Received IS NOT NULL THEN 1 ELSE 0 END NUM_RECEIVED,
CASE WHEN [Date_Completed] IS NOT NULL THEN 1 ELSE 0 END NUM_COMPLETE_OF_OPENED,
CASE WHEN A.DATE_COMPLETED IS NOT NULL THEN 1 ELSE 0 END NUM_COMPLETED_IN_MONTH,
CASE WHEN A.MFG IS NULL AND A.MFG2 IS NULL AND A.QC IS NULL AND A.QC2 IS NULL THEN 1 ELSE 0 END AS NUM_WITHOUT_ERROR
FROM
#TEMP1 a
--WHERE (a.[Group] = #GROUP or #GROUP = '' OR #GROUP IS NULL) AND A.Date_Received >= #STARTDATE AND A.Date_Received <= #ENDDATE
)
select
round(100 * SUM(A)/SUM(b) , 1) ,
SUM(NUM_RECEIVED) NUM_RECEIVED,
SUM(NUM_COMPLETE_OF_OPENED) NUM_COMPLETE_OF_OPENED,
SUM(NUM_COMPLETED_IN_MONTH) NUM_COMPLETED_IN_MONTH,
SUM(NUM_WITHOUT_ERROR) NUM_WITHOUT_ERROR
FROM CTE
Basically you need to use SUM() to get the sum. You should also use 1.0 and 0.0 so you get decimal values.
You should also do the SUM before the Division
UPDATE
Since you're adding in a number of SUM(CASE statements its probably more readable to move the CASE statments out to a CTE.
CREATE TABLE #Batch_Records (
MFG int ,
MFG2 int ,
QC int,
QC2 INT ,
[Group] int,
[Date_Completed] datetime,
Date_Received datetime)
INSERT INTO #Batch_Records (MFG , MFG2 , QC , QC2 , [Group] , [Date_Completed] , Date_Received )
VALUES (1,null,null,null,1,'1/4/2011','2/4/2011'),
(null,null,null,null,1,'2/2/2011','3/4/2011'),
(1,null,null,null,1,'3/6/2011','4/3/2011'),
(null,null,null,null,1,NULL,'5/4/2011'),
(1,null,null,null,1,'5/4/2011','6/6/2011'),
(1,null,null,null,1,NULL,'7/4/2011')
DECLARE #GROUP int
DECLARE #STARTDATE DateTime
DECLARE #ENDDATE DateTime
SET #GROUP = 1
SET #STARTDATE = '1/1/2001'
SET #ENDDATE = '1/1/2012'
;WITH CTE AS
(
SELECT
CASE
WHEN A.MFG IS NULL AND A.MFG2 IS NULL AND A.QC IS NULL AND A.QC2 IS NULL THEN
1.0
ELSE 0.0 END A,
CASE WHEN [Date_Completed] IS NOT NULL THEN
1.0 ELSE 0.0 END B,
CASE WHEN A.Date_Received IS NOT NULL THEN 1 ELSE 0 END NUM_RECEIVED,
CASE WHEN [Date_Completed] IS NOT NULL THEN 1 ELSE 0 END NUM_COMPLETE_OF_OPENED,
CASE WHEN A.DATE_COMPLETED IS NOT NULL THEN 1 ELSE 0 END NUM_COMPLETED_IN_MONTH,
CASE WHEN A.MFG IS NULL AND A.MFG2 IS NULL AND A.QC IS NULL AND A.QC2 IS NULL THEN 1 ELSE 0 END AS NUM_WITHOUT_ERROR
FROM
#Batch_Records a
WHERE
(a.[Group] = #GROUP or #GROUP = '' OR #GROUP IS NULL)
AND A.Date_Received >= #STARTDATE AND A.Date_Received <= #ENDDATE
)
select
round(100 * SUM(A)/SUM(b) , 1) ,
SUM(NUM_RECEIVED) NUM_RECEIVED,
SUM(NUM_COMPLETE_OF_OPENED) NUM_COMPLETE_OF_OPENED,
SUM(NUM_COMPLETED_IN_MONTH) NUM_COMPLETED_IN_MONTH,
SUM(NUM_WITHOUT_ERROR) NUM_WITHOUT_ERROR
FROM CTE
DROP TABLE #Batch_Records