Report Builder not counting totals correctly for some fields - tsql

I have an issue with the report totals. Some - calculated just fine. But some - shows arbitrary numbers.
I had to use nested queries, since there's additional calculations required for several fields. Below is the one I have problems with now:
with table1 as
(SELECT DISTINCT
...
, (Select SUM (x.PlanAAmt) from (SELECT SUM(Amt) AS PlanAAmt FROM PRTH AS c
WHERE c.PRCo = PREA.PRCo AND c.Employee = PREA.Employee AND c.PREndDate > CASE
WHEN DATENAME(WEEKDAY,DATEADD(Day, 60,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate ELSE PREH.RecentRehireDate END)) = 'Sunday' THEN DATEADD(DAY, 66,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate else PREH.RecentRehireDate END)
WHEN DATENAME(WEEKDAY,DATEADD(Day, 60,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate ELSE PREH.RecentRehireDate END)) = 'Monday' THEN DATEADD(DAY, 65,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate else PREH.RecentRehireDate END)
WHEN DATENAME(WEEKDAY,DATEADD(Day, 60,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate ELSE PREH.RecentRehireDate END)) = 'Tuesday' THEN DATEADD(DAY, 64,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate else PREH.RecentRehireDate END)
WHEN DATENAME(WEEKDAY,DATEADD(Day, 60,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate ELSE PREH.RecentRehireDate END)) = 'Wednesday' THEN DATEADD(DAY, 63,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate else PREH.RecentRehireDate END)
WHEN DATENAME(WEEKDAY,DATEADD(Day, 60,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate ELSE PREH.RecentRehireDate END)) = 'Thursday' THEN DATEADD(DAY, 62,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate else PREH.RecentRehireDate END)
WHEN DATENAME(WEEKDAY,DATEADD(Day, 60,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate ELSE PREH.RecentRehireDate END)) = 'Friday' THEN DATEADD(DAY, 61,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate else PREH.RecentRehireDate END)
WHEN DATENAME(WEEKDAY,DATEADD(Day, 60,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate ELSE PREH.RecentRehireDate END)) = 'Saturday' THEN DATEADD(DAY, 60,CASE WHEN PREH.RecentRehireDate IS NULL THEN PREH.HireDate else PREH.RecentRehireDate END)
END
AND (CASE WHEN PREH.RecentRehireDate IS NULL
THEN PREH.HireDate ELSE PREH.RecentRehireDate END) >= '2021-11-02 00:00:00'
FROM PREA
JOIN PREH ON PREA.PRCo = PREH.PRCo AND PREA.Employee = PREH.Employee)
select PRCo, Employee, LastName, FirstName, SSN, udSeniorityDOH, EDLType, EDLCode, Hrs, Amt, SubjAmt,EliEmt, PlanAAmt, Sum(PlanAAmt) as PlanATotals
from table1
So, as you can see - there's Sum(PlanAAmt) to check myself in same table - and everything is correct with it. But, as soon as I try to calculate totals in the report - it shows me absolutely random numbers, or nothing (some values can be null, though).
Why other column totals are correct, but this one is not? Where i'm making mistake?

Related

Tableau-Generated Query Not Hitting the Optimal Table Index

I have a tableau-generated query that looks like:
SELECT (((DATEPART(year,(CASE
WHEN 0 = ISDATE(CAST([table1].[M_Date] AS VARCHAR)) THEN NULL
ELSE DATEADD(day, DATEDIFF(day, 0, CAST(CAST([table1].[M_Date] AS VARCHAR) as datetime)), 0) END)) * 10000) + (DATEPART(month,(CASE
WHEN 0 = ISDATE(CAST([table1].[M_Date] AS VARCHAR)) THEN NULL
ELSE DATEADD(day, DATEDIFF(day, 0, CAST(CAST([table1].[M_Date] AS VARCHAR) as datetime)), 0) END)) * 100)) + DATEPART(day,(CASE
WHEN 0 = ISDATE(CAST([table1].[M_Date] AS VARCHAR)) THEN NULL
ELSE DATEADD(day, DATEDIFF(day, 0, CAST(CAST([table1].[M_Date] AS VARCHAR) as datetime)), 0) END))) AS [md:M_Date:ok]
FROM [tbl].[table] [table1]
GROUP BY (((DATEPART(year,(CASE
WHEN 0 = ISDATE(CAST([table1].[M_Date] AS VARCHAR)) THEN NULL
ELSE DATEADD(day, DATEDIFF(day, 0, CAST(CAST([table1].[M_Date] AS VARCHAR) as datetime)), 0) END)) * 10000) + (DATEPART(month,(CASE
WHEN 0 = ISDATE(CAST([table1].[M_Date] AS VARCHAR)) THEN NULL
ELSE DATEADD(day, DATEDIFF(day, 0, CAST(CAST([table1].[M_Date] AS VARCHAR) as datetime)), 0) END)) * 100)) + DATEPART(day,(CASE
WHEN 0 = ISDATE(CAST([table1].[M_Date] AS VARCHAR)) THEN NULL
ELSE DATEADD(day, DATEDIFF(day, 0, CAST(CAST([table1].[M_Date] AS VARCHAR) as datetime)), 0) END)))
table 'table' has two indexes:
A clustered index over the columns [M_Date], [Team], [Player], [Second].
A non-unique, non-clustered index over the columns [Player], [M_Date], [Team]
When I look at the Execution Plan for the query, it tells me that the second index is being used. This seems strange to me because I thought that an index could only be used if the columns involved form 'a leftmost prefix of the index' (as explained here) which this query does not. If anyone could explain what it is I am not understanding, or if this is just an odd case where the incorrect index is getting used, your help would be much appreciated!

Find the missing hour with Lag analytic function

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

PostgreSQL Select join table and a function

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.

Telerik's RadGridView + WCF Data Services + Entity Framework = Terrible performance

We have a simple LOB application that:
pulls data from EF
serves data across the wire with WCF Data Services
renders that data on Telerik's RadGridView
This works really well in the default scenario as users are able to filter data by using the built-in Telerik filter control which presents all the options they want.
The problem happens when re-constructing the query sent from WCF Data Services when the 'Contains' operator is used:
WCF Data Services adds a bunch of "IIF" lambda expressions which,
EF then expands into T-SQL CASE statements
This takes a query that should look like:
SELECT TOP (25)
[Project1].[TaskID] AS [TaskID],
[Project1].[ProductSubmissionID] AS [ProductSubmissionID],
...
FROM ( SELECT
[Extent1].[TaskID] AS [TaskID],
[Extent1].[ProductSubmissionID] AS [ProductSubmissionID],
...
FROM [dbo].[Task] AS [Extent1]
LEFT OUTER JOIN [dbo].[OperationDataProduct] AS [Extent2] ON [Extent1].[ProductID] = [Extent2].[ProductID]
LEFT OUTER JOIN [dbo].[vProductOwnership] AS [Extent3] ON [Extent1].[ProductID] = [Extent3].[ProductID]
LEFT OUTER JOIN [dbo].[User] AS [Extent4] ON [Extent2].[ChannelManagerID] = [Extent4].[UserID]
LEFT OUTER JOIN [dbo].[User] AS [Extent5] ON [Extent2].[ProductOwnerID] = [Extent5].[UserID]
WHERE [Extent1].Type IN ('Content','Concept','Financial') AND [Extent1].MarketplaceName LIKE '%prod%'
Into one that looks like this:
SELECT TOP (25)
[Project1].[TaskID] AS [TaskID],
[Project1].[ProductSubmissionID] AS [ProductSubmissionID],
...
FROM ( SELECT
[Extent1].[TaskID] AS [TaskID],
[Extent1].[ProductSubmissionID] AS [ProductSubmissionID],
...
FROM [dbo].[Task] AS [Extent1]
LEFT OUTER JOIN [dbo].[OperationDataProduct] AS [Extent2] ON [Extent1].[ProductID] = [Extent2].[ProductID]
LEFT OUTER JOIN [dbo].[vProductOwnership] AS [Extent3] ON [Extent1].[ProductID] = [Extent3].[ProductID]
LEFT OUTER JOIN [dbo].[User] AS [Extent4] ON [Extent2].[ChannelManagerID] = [Extent4].[UserID]
LEFT OUTER JOIN [dbo].[User] AS [Extent5] ON [Extent2].[ProductOwnerID] = [Extent5].[UserID]
WHERE (CASE WHEN (CASE WHEN (((CASE WHEN (CASE WHEN ([Extent1].[MarketplaceName] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE LOWER([Extent1].[MarketplaceName]) END IS NULL) THEN CAST(NULL AS bit) WHEN (CASE WHEN ([Extent1].[MarketplaceName] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE LOWER([Extent1].[MarketplaceName]) END LIKE N'%prod%') THEN cast(1 as bit) WHEN ( NOT (CASE WHEN ([Extent1].[MarketplaceName] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE LOWER([Extent1].[MarketplaceName]) END LIKE N'%prod%')) THEN cast(0 as bit) END) = 1) AND ([Extent1].[SubmissionOrTaskType] IN (N'Content',N'Concept',N'Financial'))) THEN cast(1 as bit) WHEN ( NOT (((CASE WHEN (CASE WHEN ([Extent1].[MarketplaceName] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE LOWER([Extent1].[MarketplaceName]) END IS NULL) THEN CAST(NULL AS bit) WHEN (CASE WHEN ([Extent1].[MarketplaceName] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE LOWER([Extent1].[MarketplaceName]) END LIKE N'%prod%') THEN cast(1 as bit) WHEN ( NOT (CASE WHEN ([Extent1].[MarketplaceName] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE LOWER([Extent1].[MarketplaceName]) END LIKE N'%prod%')) THEN cast(0 as bit) END) = 1) AND ([Extent1].[SubmissionOrTaskType] IN (N'Content',N'Concept',N'Financial')))) THEN cast(0 as bit) END IS NULL) THEN cast(0 as bit) WHEN (((CASE WHEN (CASE WHEN ([Extent1].[MarketplaceName] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE LOWER([Extent1].[MarketplaceName]) END IS NULL) THEN CAST(NULL AS bit) WHEN (CASE WHEN ([Extent1].[MarketplaceName] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE LOWER([Extent1].[MarketplaceName]) END LIKE N'%prod%') THEN cast(1 as bit) WHEN ( NOT (CASE WHEN ([Extent1].[MarketplaceName] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE LOWER([Extent1].[MarketplaceName]) END LIKE N'%prod%')) THEN cast(0 as bit) END) = 1) AND ([Extent1].[SubmissionOrTaskType] IN (N'Content',N'Concept',N'Financial'))) THEN cast(1 as bit) WHEN ( NOT (((CASE WHEN (CASE WHEN ([Extent1].[MarketplaceName] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE LOWER([Extent1].[MarketplaceName]) END IS NULL) THEN CAST(NULL AS bit) WHEN (CASE WHEN ([Extent1].[MarketplaceName] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE LOWER([Extent1].[MarketplaceName]) END LIKE N'%prod%') THEN cast(1 as bit) WHEN ( NOT (CASE WHEN ([Extent1].[MarketplaceName] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE LOWER([Extent1].[MarketplaceName]) END LIKE N'%prod%')) THEN cast(0 as bit) END) = 1) AND ([Extent1].[SubmissionOrTaskType] IN (N'Content',N'Concept',N'Financial')))) THEN cast(0 as bit) END) = 1
) AS [Project1]
ORDER BY [Project1].[TaskID] ASC
My question is: has anyone bumped into this problem before and is there a low cost solution?
I can see re-writing the EF QueryProvider to be a solution, but it's not exactly low cost.
TIA
We wound up writing a QueryProvider to fix this issue. It wound up being lower cost than originally expected, but still adds quiet a bit of unnecessary complexity. The IQToolkit has some decent examples of how to begin this.

SQL Rows to Columns, PIVOT probably would work but not sure how with multiple columns

I've got a poorly designed table, that has a mixture of rows and columns, where it probably should have had 1 row with many many columns or some other design entirely. But that mistake was 20 years ago, on someone else's watch.
Right now I'm accomplishing the view I want with a myriad of self-joins. This is painfully slow.
The following will set up how I'm doing at the moment:
declare #client table
(
clientNumber int,
name varchar(10)
)
insert into #client values (1, 'Bob');
insert into #client values (2, 'Alice');
declare #options table
(
clientNumber int,
optionKey varchar(4),
optionValue1 int,
optionValue2 int,
optionValue3 int
)
insert into #options values (1, 'optA', 1, 1, 0);
insert into #options values (1, 'optB', 0, 1, 0);
insert into #options values (2, 'optA', 1, 1, 1);
insert into #options values (2, 'optC', 0, 0, 1);
select c.clientNumber, c.name,
oA.optionValue1 as [Graduated],
oA.optionValue2 as [Employed],
oA.optionValue3 as [Married],
oB.optionValue1 as [HasPets],
oB.optionValue2 as [LikesThai],
oB.optionValue3 as [MathWiz],
oC.optionValue1 as [DrvLicense],
oC.optionValue2 as [Registered],
oC.optionValue3 as [Outdoorsy]
from #client c
left outer join #options oA
on oA.clientNumber = c.clientNumber and oA.optionKey = 'optA'
left outer join #options oB
on oB.clientNumber = c.clientNumber and oB.optionKey = 'optB'
left outer join #options oC
on oC.clientNumber = c.clientNumber and oC.optionKey = 'optC'
For these results:
The result set is exactly what I want. Not every client has an A, B, or C record so the null in the result set is fine. I can't find an example like this after a while of searching so I'm not sure PIVOT is really what I'm looking for. Suggestions?
Update:
this seems to produce the same results. I'm going to test it on the much larger case to see if it's faster than all of the self-joins. (I suspect it is). I'd still like to know if I'm barking up the wrong tree with pivots.
select clientNumber,
Min(Case o.optionKey when 'optA' then o.optionValue1 end) [Graduated],
Min(Case o.optionKey when 'optA' then o.optionValue2 end) [Employed],
Min(Case o.optionKey when 'optA' then o.optionValue3 end) [Married],
Min(Case o.optionKey when 'optB' then o.optionValue1 end) [HasPets],
Min(Case o.optionKey when 'optB' then o.optionValue2 end) [LikesThai],
Min(Case o.optionKey when 'optB' then o.optionValue3 end) [MathWix],
Min(Case o.optionKey when 'optC' then o.optionValue1 end) [DrvLicense],
Min(Case o.optionKey when 'optC' then o.optionValue2 end) [Registered],
Min(Case o.optionKey when 'optC' then o.optionValue3 end) [Outdoorsy]
from #options o
group by clientnumber
Here are a couple of options. Both solutions use a technique that pivots the data. The first solution will change your NULLs to 0.
SELECT c.clientNumber, c.name,
MAX(CASE WHEN o.optionKey = 'optA' THEN o.optionValue1 ELSE 0 END) AS [Graduated],
MAX(CASE WHEN o.optionKey = 'optA' THEN o.optionValue2 ELSE 0 END) AS [Employed],
MAX(CASE WHEN o.optionKey = 'optA' THEN o.optionValue3 ELSE 0 END) AS [Married],
MAX(CASE WHEN o.optionKey = 'optB' THEN o.optionValue1 ELSE 0 END) AS [HasPets],
MAX(CASE WHEN o.optionKey = 'optB' THEN o.optionValue2 ELSE 0 END) AS [LikesThai],
MAX(CASE WHEN o.optionKey = 'optB' THEN o.optionValue3 ELSE 0 END) AS [MathWiz],
MAX(CASE WHEN o.optionKey = 'optC' THEN o.optionValue1 ELSE 0 END) AS [DrvLicense],
MAX(CASE WHEN o.optionKey = 'optC' THEN o.optionValue2 ELSE 0 END) AS [Registered],
MAX(CASE WHEN o.optionKey = 'optC' THEN o.optionValue3 ELSE 0 END) AS [Outdoorsy]
FROM #client c
LEFT OUTER JOIN #options o
ON o.clientNumber = c.clientNumber
GROUP BY c.clientNumber, c.name
ORDER BY c.clientNumber, c.name
The second solution preserves the NULL values. However, it requires an explicit type conversion from BIT to TINYINT, because the MAX function fails on BIT data types.
SELECT c.clientNumber, c.name,
MAX(CASE WHEN o.optionKey = 'optA' THEN CAST (o.optionValue1 AS TINYINT) END) AS [Graduated],
MAX(CASE WHEN o.optionKey = 'optA' THEN CAST (o.optionValue2 AS TINYINT) END) AS [Employed],
MAX(CASE WHEN o.optionKey = 'optA' THEN CAST (o.optionValue3 AS TINYINT) END) AS [Married],
MAX(CASE WHEN o.optionKey = 'optB' THEN CAST (o.optionValue1 AS TINYINT) END) AS [HasPets],
MAX(CASE WHEN o.optionKey = 'optB' THEN CAST (o.optionValue2 AS TINYINT) END) AS [LikesThai],
MAX(CASE WHEN o.optionKey = 'optB' THEN CAST (o.optionValue3 AS TINYINT) END) AS [MathWiz],
MAX(CASE WHEN o.optionKey = 'optC' THEN CAST (o.optionValue1 AS TINYINT) END) AS [DrvLicense],
MAX(CASE WHEN o.optionKey = 'optC' THEN CAST (o.optionValue2 AS TINYINT) END) AS [Registered],
MAX(CASE WHEN o.optionKey = 'optC' THEN CAST (o.optionValue3 AS TINYINT) END) AS [Outdoorsy]
FROM #client c
LEFT OUTER JOIN #options o
ON o.clientNumber = c.clientNumber
GROUP BY c.clientNumber, c.name
ORDER BY c.clientNumber, c.name
I am not sure about its performance, but I would do it this way:
select c.clientNumber, c.name,
oA.optionValue1 as [Graduated],
oA.optionValue2 as [Employed],
oA.optionValue3 as [Married],
oB.optionValue1 as [HasPets],
oB.optionValue2 as [LikesThai],
oB.optionValue3 as [MathWiz],
oC.optionValue1 as [DrvLicense],
oC.optionValue2 as [Registered],
oC.optionValue3 as [Outdoorsy]
from #client c
OUTER APPLY (SELECT * FROM #options WHERE optionkey = 'optA' And clientnumber = c.clientnumber) oA
OUTER APPLY (SELECT * FROM #options WHERE optionkey = 'optB' And clientnumber = c.clientnumber) oB
OUTER APPLY (SELECT * FROM #options WHERE optionkey = 'optC' And clientnumber = c.clientnumber) oC
or CTE might be useful
with t as
(select oA.ClientNumber,
oA.optionValue1 as [Graduated],
oA.optionValue2 as [Employed],
oA.optionValue3 as [Married],
oB.optionValue1 as [HasPets],
oB.optionValue2 as [LikesThai],
oB.optionValue3 as [MathWiz],
oC.optionValue1 as [DrvLicense],
oC.optionValue2 as [Registered],
oC.optionValue3 as [Outdoorsy]
from
(SELECT * FROM #options WHERE optionkey = 'optA') oA
OUTER APPLY (SELECT * FROM #options WHERE optionkey = 'optB' And clientnumber = oA.clientnumber) oB
OUTER APPLY (SELECT * FROM #options WHERE optionkey = 'optC' And clientnumber = oA.clientnumber) oC )
select c.clientNumber, c.name,
t.[Graduated],
t.[Employed],
t.[Married],
t.[HasPets],
t.[LikesThai],
t.[MathWiz],
t.[DrvLicense],
t.[Registered],
t.[Outdoorsy]
from #client c join t on c.clientnumber = t.clientnumber