Not does not exclude query info - sql

I have a really long query and I'm finding that my NOT is not excluding what's in parenthesis after the NOT.
I saw Exclude and where not exists, but I'd have to re-select for that, and there's too many complicatedly joined tables in what I selected already, plus one table is very big and takes a long time to select what I have already, so I can't re-select because it will make the query take too long. How do I get this exclusion to work?
INSERT INTO #UNeedingC(id, CASEID, firstname, lastname, userid, AGEOFNOTIFICATION, DATETIMEDECISIONMADE, DELEGATESYSTEM, Person_id, request_type_id, service_place_id, status_summary, externalUserId, subject, onDate, externalPersonId, externalSystemId)
select distinct
c.id
,uc.case_id
,t_case.FIRSTNAME as first
,t_case.LASTNAME as last
,t_case.user_id as userid
,CONVERT(VARCHAR, DATEDIFF(dd, SC.status_change_date, GETDATE())) + ' Day(s) ' + CONVERT(VARCHAR, DATEDIFF(hh, SC.status_change_date, GETDATE()) % 24) + ' Hour(s) ' as [AGE OF NOTIFICATION]
,SC.status_change_date AS [DATE TIME DECISION MADE]
,[ckoltp_sys].DBO.ckfn_GetStringLocaleValue(152,9,uc.delegate_system,50,0) AS [DELEGATESYSTEM]
,c.person_id
,uc.request_type_id ------
,uc.service_place_id
,uc.status_summary
,eou.external_id
,c.tzix_id+' '+[ckoltp_sys].dbo.ckfn_GetStringLocaleValue(148,9,uc.status_summary,5,0)+' type' AS subject
,dateadd( hour,41,dateadd(day,0,datediff(d,0,sc.status_change_date)) ) AS onDate
,emd.externalId externalPersonId
,eou.system_id as externalSystemId
--,u.disable
from
#tempC t_case with (NOLOCK)
inner join dbo.org_case c with (nolock) ON t_case.Person_id=c.Person_id
INNER JOIN dbo.org_2_case uc with (NOLOCK) ON uc.case_id=c.id
inner JOIN dbo.ORG_LOS S WITH (NOLOCK) ON S.case_id = UC.case_id
inner JOIN dbo.ORG_EXTENSION SC WITH (NOLOCK) ON SC.los_id= S.id
inner join dbo.org_user u with (NOLOCK) on u.id=t_case.user_id
inner join dbo.org_person op with (NOLOCK) on op.id=c.Person_id
inner JOIN dbo.u_person_concept_value MC ON MC.CID = op.cid --this is the slow table
inner join dbo.EXTERNAL_ORG_USER_DATA eou with (NOLOCK) ON eou.org_user_id = t_case.user_id
inner join dbo.EXTERNAL_person_DATA emd with (NOLOCK) ON emd.CID = op.cid --op.id --?
WHERE
DATEDIFF(day, SC.status_change_date , GETDATE()) <= 2
AND
u.disable <> 1
AND
( --(denied/approved)
dbo.ckfn_GetStringLocaleValue(148,9,uc.status_summary,5,0) = 'Denied'
OR
(dbo.ckfn_GetStringLocaleValue(148,9,uc.status_summary,5,0) in( 'Fully Approved', 'Partially Approved'))
)
AND
(
(
ISNULL(uc.request_type_id,'') in( 12)
AND DATEDIFF(month, SC.status_change_date , GETDATE()) <= 2
)
OR
(
ISNULL(uc.request_type_id,'') in( 10,11)
)
--OR
--(
-- --exclude this
-- (
-- MC.concept_id = '501620' --general val1 (1000/1001)
-- AND
-- (C.ID in (select case_id from #CASES where str_value in ('1000','1001'))
-- AND (uc.service_place_id = 31 OR uc.service_place_id = 32))
-- ) --not
--) --or
)--AND
AND
(t_case.firstname not like '%external%' and t_case.lastname not like '%case manager%')
AND
(
C.ID in (select case_id from #CASES where concept_id='501620')--MC.concept_id = '501620'
)
--overall around AND (denied/approved)--
and DBO.ckfn_GetStringLocaleValue(152,9,uc.delegate_system,50,0) in ('AP','CA')
AND NOT --this not is not working...this appears in query results
(
--exclude these
(
MC.concept_id = '501620'
AND
(C.ID in (select case_id from #CASES where str_value in ('1000','1001'))
AND (uc.service_place_id = 31 OR uc.service_place_id = 32))
) --not
) --
select * from #UNeedingC
results show what is excluded:
id caseid firstname lastname userid ageofNotification Datetimedecisionmade DelegateSys Person_id request_type_id service_place_id status_summary externalUserId subject
onDate externalPersonId externalSystemId
000256200 256200 Sree Par 1234 0 Apr 5 CA
4270000 11 31 3 sparee 000256200 Fully Approved tested Ad 2021-04-06 17:00 363000 2
My question: do you know why the NOT is not working and how I can get this to exclude without another select? See "this not is not working" comment. I searched online but only found exclude and where not exists, which require another select, which I don't want.

I think I figured it out: "NOT acts on one condition. To negate two or more conditions, repeat the NOT for each condition,"
from not on two things.
This seems to work:
...
AND
--exclude these
(
MC.concept_id = '501620' --general val1 (1000/1001)
AND
(C.ID not in (select case_id from #CASES where str_value in ('1000','1001'))
AND (uc.service_place_id not in ('31','32')))
) --not

Related

Joining tables inflates number values

Here is my query, I have different account values (the accValByProd table) that I want to add to my table by their product type. If I just select the accValByProd table by itself the numbers are accurate, but when I join it with the billing table the numbers become much larger than they should be.
As you can see since I need to take the MAX of values in the billing table and then SUM them in the final calculation, I can't just do that in the final SELECT (unless there's a way to do that?). Any help is appreciated I'm not quite sure what I'm doing wrong.
WITH billing AS
( SELECT
bh.debit_account_id,
bh.period_start_date,
bh.period_end_date,
bh.a_id,
bh.account_value,
bh.platform_fee
FROM
billing_history bh
WHERE
-- LESS than same day following year includes any
-- possible time portion if so part of.
bh.period_start_date >= '2020-07-01'
and bh.period_end_date < '2021-07-01'
and bh.a_fee != 0
),
acc_prods AS
(
SELECT
a.account_id,
a.product_id,
CASE WHEN p.product_type = 3 THEN 'FSP'
WHEN p.product_type = 6 THEN 'APM'
WHEN p.product_type = 13 THEN 'UMA'
ELSE 'Unknown' END product_type,
a.a_id
FROM
account a
LEFT JOIN product p
ON a.product_id = p.product_id
WHERE
-- which table alias, should never leave blind
-- assumption here is "Account" table (alias a)
a.close_date IS NULL
OR a.close_date >= GETDATE()
),
accounts AS (
SELECT
a.account_id,
a.a_id,
a.customer_id,
a.close_date
FROM
account a
),
accValByProd as
(
SELECT
bh.debit_account_id AS deb_id,
bh.period_end_date,
MAX(bh.account_value) AS acc_val,
bh.a_id,
ISNULL(ap.product_type, 'Unknown') AS prod_type
FROM
billing_history bh
LEFT JOIN acc_prods ap
ON bh.debit_account_id = ap.account_id
WHERE
bh.period_end_date = '2021-06-30'
GROUP BY
bh.debit_account_id,
bh.period_end_date,
bh.a_id,
ap.product_type
)
SELECT DISTINCT
ad.ad_id,
ad.fname + ' ' + ad.middle + ' ' + ad.lname 'full name',
accValByProd.prod_type AS 'product type',
COUNT(DISTINCT billing.debit_account_id) AS 'number of accounts',
SUM(accValByProd.acc_val) AS 'product aum',
SUM(CASE WHEN DATEDIFF(DAY, billing.period_start_date, billing.period_end_date) > 31
THEN billing.platform_fee ELSE 0 END) AS 'fees'
FROM
advisor ad
JOIN billing
ON ad.a_id = billing.a_id
JOIN accounts
ON billing.debit_account_id = accounts.account_id
JOIN accValByProd
ON billing.debit_account_id = accValByProd.deb_id
WHERE
1=1
and ( ad.termination_date IS NULL
OR ad.termination_date >= GETDATE())
AND ( accounts.close_date IS NULL
OR accounts.close_date >= '2021-06-30')
GROUP BY
ad.a_id,
ad.fname,
ad.middle,
ad.lname,
accValByProd.prod_type
Here are the expected results for a_id 6835 (plus the other information)
a_id product aum product type
---- ------------ -------------
6835 7861895.23 APM
6835 47059722.64 FSP
6835 9816992.32 UMA
6835 528930.47 Unknown
And here are the actual results:
a_id product aum product type
---- ------------ -------------
6835 45447953.20 APM
6835 203942000.07 FSP
6835 77678383.30 UMA
6835 1706276.86 Unknown

create an classification for months ordered

I'm trying to create an column in my query to show an ordered classification ( show 1, 2, 3 ( as in first, second, third ...)) relative to date... in my current query i have filtered data from the last 12 months ( as example, from 1-9-2016 to 31-8-2017)
using DATEADD(mm; DATEDIFF(m; - 1; GETDATE()) - 12; 0)
for the first date and
DATEADD(s; - 1; DATEADD(mm; DATEDIFF(m; 0; GETDATE()) + 1; 0))
for the last day of the current month. And i also have two columns, one with the month and other with the year, both extracted from a document date column present in the data ( i'm using
MONTH(dbo.Mov_Venda_Cab.dtmData) and YEAR(dbo.Mov_Venda_Cab.dtmData)).
My goal is to have a column showing something like this :
If the month is the first from the interval ( if is month 9 and year 2016 ) is has to show 1 , if is the second ( month 10 and year 2016) , show 2, all continuously until the current month ( that is 8 and year 2017) and showing 12.
If the values where static i could do a simple case and would achieve what i wanted. My problem is that since when i get the data filtered by my current date and the 12 months behind, i don't manage to get the same result because i don't know exactly what i should do in the CASE expression.
so that it could help my columns are :
Item ; Qty ; Month ; Year ; dtmData ; orderedMonth
ORIGINAL QUERY :
SELECT DISTINCT DATEADD(mm, DATEDIFF(m, - 1, GETDATE()) - 12, 0) AS DATA_INI,
DATEADD(s, - 1, DATEADD(mm, DATEDIFF(m, 0, GETDATE()) + 1, 0)) AS DATA_FIM,
dbo.Mov_Venda_Lin.Id,
MONTH(dbo.Mov_Venda_Cab.dtmData) AS Mes,
YEAR(dbo.Mov_Venda_Cab.dtmData) AS Ano,
dbo.Mov_Venda_Lin.fltValorMercadoriaSIVA * dbo.Mov_Venda_Cab.intSinal AS Mercadoria,
dbo.Mov_Venda_Lin.fltValorLiquido * dbo.Mov_Venda_Cab.intSinal AS ValorLiquido,
CASE
WHEN tbl_tipos_documentos.bitconsideraqtdmapas = 1
THEN (Mov_Venda_Lin.fltQuantidade * mov_venda_cab.intsinal)
ELSE 0
END AS Quantidade,
dbo.Mov_Venda_Lin.strCodSeccao AS Seccao,
dbo.Mov_Venda_Lin.strAbrevTpDoc AS TpDoc,
dbo.Tbl_Tipos_Documentos.strDescricao AS DescTpDoc,
dbo.Mov_Venda_Lin.intNumLinha AS Linha,
dbo.Mov_Venda_Lin.strCodExercicio AS Exercicio,
dbo.Mov_Venda_Cab.strAbrevMoeda AS Moeda,
dbo.Mov_Venda_Cab.fltCambio AS Cambio,
dbo.Mov_Venda_Lin.strCodArtigo AS Artigo,
dbo.Tbl_Gce_Artigos.strDescricao AS DescArtigo,
dbo.Mov_Venda_Lin.strCodClassMovStk AS MovStk,
dbo.Tbl_ClassificacaoMovStk.strDescricao AS DescMovStk,
CASE
WHEN mov_venda_cab.inttpentidade = 0
THEN tbl_gce_tipos_entidade.strcodigo
ELSE NULL
END AS TpEntidade,
CASE
WHEN mov_venda_cab.inttpentidade = 0
THEN tbl_gce_tipos_entidade.strdescricao
ELSE NULL
END AS DescTpEntidade,
CASE
WHEN mov_venda_cab.intcodentidade <> 0
THEN mov_venda_cab.intcodentidade
ELSE NULL
END AS CodEntidade,
CASE
WHEN mov_venda_cab.inttpentidade = 0
AND mov_venda_cab.intcodentidade <> 0
THEN 'Cliente'
WHEN mov_venda_cab.inttpentidade = 1
AND mov_venda_cab.intcodentidade <> 0
THEN 'Outro Devedor'
ELSE NULL
END AS TipoEntidade,
CASE
WHEN mov_venda_cab.inttpentidade = 0
THEN tbl_clientes.strnome
ELSE tbl_outros_devedores.strnome
END AS DescNome,
dbo.Tbl_SubZonas.strAbrevZona AS Zona,
dbo.Tbl_Zonas.strDescricao AS DescZona,
dbo.Mov_Venda_Cab.strAbrevSubZona AS SubZona,
dbo.Tbl_SubZonas.strDescricao AS DescSubZona,
dbo.Mov_Venda_Cab.intCodVendedor AS Vendedor,
dbo.Tbl_Gce_Vendedores.strNome AS DescNomeVend,
dbo.Tbl_Gce_Artigos.strCodCategoria AS Categoria,
dbo.Tbl_Gce_Categorias.strDescricao AS DescCategoria,
dbo.Tbl_Gce_Artigos.strTpArtigo AS TpArtigo,
dbo.Tbl_Gce_Tipos_Artigos.strDescricao AS DescTpArtigo,
CAST(NULL AS VARCHAR(13)) AS CodFamiliaAgrup,
CAST(NULL AS VARCHAR(35)) AS DescFamAgrup,
CAST(NULL AS VARCHAR(13)) AS CodFamiliaRes,
CAST(NULL AS VARCHAR(35)) AS DescFamRes,
dbo.Mov_Venda_Cab.strForteAbrevMoeda AS abrevmoeda,
dbo.Mov_Venda_Cab.fltForteCambio AS fortecambio
FROM dbo.Mov_Venda_Lin WITH (NOLOCK)
LEFT OUTER JOIN dbo.Mov_Venda_Cab WITH (NOLOCK)
ON dbo.Mov_Venda_Lin.strCodSeccao = dbo.Mov_Venda_Cab.strCodSeccao
AND dbo.Mov_Venda_Lin.strAbrevTpDoc = dbo.Mov_Venda_Cab.strAbrevTpDoc
AND dbo.Mov_Venda_Lin.strCodExercicio = dbo.Mov_Venda_Cab.strCodExercicio
AND dbo.Mov_Venda_Lin.intNumero = dbo.Mov_Venda_Cab.intNumero
LEFT OUTER JOIN dbo.Tbl_Gce_Armazens WITH (NOLOCK)
ON dbo.Mov_Venda_Lin.strCodArmazem = dbo.Tbl_Gce_Armazens.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Artigos WITH (NOLOCK)
ON dbo.Tbl_Gce_Artigos.strCodigo = dbo.Mov_Venda_Lin.strCodArtigo
LEFT OUTER JOIN dbo.Tbl_Gce_ArtigosFamilias WITH (NOLOCK)
ON dbo.Tbl_Gce_Artigos.strCodigo = dbo.Tbl_Gce_ArtigosFamilias.strCodArtigo
LEFT OUTER JOIN dbo.Tbl_Gce_Familias WITH (NOLOCK)
ON dbo.Tbl_Gce_ArtigosFamilias.strCodFamilia = dbo.Tbl_Gce_Familias.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_ArtigosReferencias WITH (NOLOCK)
ON dbo.Tbl_Gce_Artigos.strCodigo = dbo.Tbl_Gce_ArtigosReferencias.strCodArtigo
LEFT OUTER JOIN dbo.Tbl_Gce_Referencias WITH (NOLOCK)
ON dbo.Tbl_Gce_ArtigosReferencias.strCodReferencia = dbo.Tbl_Gce_Referencias.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Tipos_Artigos WITH (NOLOCK)
ON dbo.Tbl_Gce_Artigos.strTpArtigo = dbo.Tbl_Gce_Tipos_Artigos.strCodigo
LEFT OUTER JOIN dbo.Tbl_Clientes WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.intCodEntidade = dbo.Tbl_Clientes.intCodigo
LEFT OUTER JOIN dbo.Tbl_Direccoes WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.intCodEntidade = dbo.Tbl_Direccoes.intCodigo
AND dbo.Mov_Venda_Cab.intDireccao = dbo.Tbl_Direccoes.intNumero
AND dbo.Mov_Venda_Cab.intTpEntidade = dbo.Tbl_Direccoes.intTp_Entidade
LEFT OUTER JOIN dbo.Tbl_Outros_Devedores WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.intCodEntidade = dbo.Tbl_Outros_Devedores.intCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Vendedores WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.intCodVendedor = dbo.Tbl_Gce_Vendedores.intCodigo
LEFT OUTER JOIN dbo.Tbl_Tipos_Documentos WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.strAbrevTpDoc = dbo.Tbl_Tipos_Documentos.strAbreviatura
LEFT OUTER JOIN dbo.Tbl_SubZonas WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.strAbrevSubZona = dbo.Tbl_SubZonas.strAbreviatura
LEFT OUTER JOIN dbo.Tbl_Zonas WITH (NOLOCK)
ON dbo.Tbl_SubZonas.strAbrevZona = dbo.Tbl_Zonas.strAbreviatura
LEFT OUTER JOIN dbo.Tbl_Gce_Categorias WITH (NOLOCK)
ON dbo.Tbl_Gce_Artigos.strCodCategoria = dbo.Tbl_Gce_Categorias.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Seccoes WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.strCodSeccao = dbo.Tbl_Gce_Seccoes.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Tipos_Entidade WITH (NOLOCK)
ON dbo.Tbl_Clientes.strTpEntidade = dbo.Tbl_Gce_Tipos_Entidade.strCodigo
LEFT OUTER JOIN dbo.Tbl_ClassificacaoMovStk WITH (NOLOCK)
ON dbo.Mov_Venda_Lin.strCodClassMovStk = dbo.Tbl_ClassificacaoMovStk.strCodigo
WHERE (dbo.Mov_Venda_Cab.intTpEntidade = 0
OR dbo.Mov_Venda_Cab.intTpEntidade IS NULL)
AND (dbo.Mov_Venda_Cab.strAbrevTpDoc IN ('CRFCX', 'FACIV', 'FACTC', 'FCTA', 'LANIV', 'LOFX', 'LONC', 'LXANI', 'NCFCX', 'NFACC', 'NFACE', 'NFACM', 'NFACT', 'NNCRC', 'NNCRE', 'NNCRM', 'NNDEB', 'NNDEC', 'NNDEV', 'NVDIC', 'NVDIN', 'XLACC', 'XLACD'))
AND (dbo.Mov_Venda_Cab.strCodSeccao IN ('1', 'ENCT1', 'ENCT2', 'ENCT3', 'ENCT4', 'ENCT5', 'ENCT6'))
AND (dbo.Mov_Venda_Cab.dtmData > DATEADD(mm, DATEDIFF(m, - 1, GETDATE()) - 12, 0))
AND (dbo.Mov_Venda_Cab.dtmData <= DATEADD(s, - 1, DATEADD(mm, DATEDIFF(m, 0, GETDATE()) + 1, 0)))
AND (dbo.Mov_Venda_Lin.intTpLinha > 2)
AND (dbo.Mov_Venda_Cab.bitAnulado = 0)
AND (dbo.Mov_Venda_Cab.bitConvertido = 0)
Luckily there's a much less complicated method than using a bunch of CASE statements. You can use the ROW_NUMBER function.
First, don't split your dates into month and year. Just use Getdate() to calculate your desired range and compare your source dates to that. Then you add the ROW_NUMBER to get your ordering output:
SELECT
*
,ordered_output = (ROW_NUMBER()OVER(PARTITION BY grouping_field ORDER BY cast(dtmData as datetime) ASC))
FROM Mov_Venda_Cab
WHERE cast(dtmData as datetime) >= getdate() - 365
This example assumes your have some ID field or similar on which your want to group your output, represented by grouping_field in the example. Your results would look like:
grouping_field dtmData ordered_output
1 8/1/2017 1
1 8/2/2017 2
1 8/3/2017 3
2 8/1/2017 1
2 8/2/2017 2
2 8/3/2017 3
If you don't want to group your output, just ordering everything by the date, you can omit the PARTITION BY grouping_field text. You'd get instead something like:
dtmData ordered_output
8/1/2017 1
8/2/2017 2
8/3/2017 3
8/4/2017 4
8/5/2017 5
8/6/2017 6
EDIT: Asker clarified that all records with the same month should get the same ordered output.
To do that you first need to assign each month/year combo a rank and rejoin that to the main table using two layers of subqueries:
SELECT b.*, c.month_rank
from Mov_Venda_Cab as b
inner join
(select mnt, yr, ROW_NUMBER() OVER(ORDER BY A.yr, A.mnt) AS month_rank
from (
SELECT DISTINCT
MONTH(dtmData) as mnt
, YEAR(dtmData) as yr
from Mov_Venda_Cab
WHERE cast(dtmData as datetime) >= getdate() - 365
) as a
) as c
on MONTH(b.dtmData) = c.mnt and YEAR(b.dtmData) = c.yr

SQL Server / T-SQL : query optimization assistance

I have this QA logic that looks for errors into every AuditID within a RoomID to see if their AuditType were never marked Complete or if they have two complete statuses. Finally, it picks only the maximum AuditDate of the RoomIDs with errors to avoid showing multiple instances of the same RoomID, since there are many audits per room.
The issue is that the AUDIT table is very large and takes a long time to run. I was wondering if there is anyway to reach the same result faster.
Thank you in advance !
IF object_ID('tempdb..#AUDIT') is not null drop table #AUDIT
IF object_ID('tempdb..#ROOMS') is not null drop table #ROOMS
IF object_ID('tempdb..#COMPLETE') is not null drop table #COMPLETE
IF object_ID('tempdb..#FINALE') is not null drop table #FINALE
SELECT distinct
oc.HotelID, o.RoomID
INTO #ROOMS
FROM dbo.[rooms] o
LEFT OUTER JOIN dbo.[hotels] oc on o.HotelID = oc.HotelID
WHERE
o.[status] = '2'
AND o.orderType = '2'
SELECT
t.AuditID, t.RoomID, t.AuditDate, t.AuditType
INTO
#AUDIT
FROM
[dbo].[AUDIT] t
WHERE
t.RoomID IN (SELECT RoomID FROM #ROOMS)
SELECT
t1.RoomID, t3.AuditType, t3.AuditDate, t3.AuditID, t1.CompleteStatus
INTO
#COMPLETE
FROM
(SELECT
RoomID,
SUM(CASE WHEN AuditType = 'Complete' THEN 1 ELSE 0 END) AS CompleteStatus
FROM
#AUDIT
GROUP BY
RoomID) t1
INNER JOIN
#AUDIT t3 ON t1.RoomID = t3.RoomID
WHERE
t1.CompleteStatus = 0
OR t1.CompleteStatus > 1
SELECT
o.HotelID, o.RoomID,
a.AuditID, a.RoomID, a.AuditDate, a.AuditType, a.CompleteStatus,
c.ClientNum
INTO
#FINALE
FROM
#ROOMS O
LEFT OUTER JOIN
#COMPLETE a on o.RoomID = a.RoomID
LEFT OUTER JOIN
[dbo].[clients] c on o.clientNum = c.clientNum
SELECT
t.*,
Complete_Error_Status = CASE WHEN t.CompleteStatus = 0
THEN 'Not Complete'
WHEN t.CompleteStatus > 1
THEN 'Complete More Than Once'
END
FROM
#FINALE t
INNER JOIN
(SELECT
RoomID, MAX(AuditDate) AS MaxDate
FROM
#FINALE
GROUP BY
RoomID) tm ON t.RoomID = tm.RoomID AND t.AuditDate = tm.MaxDate
One section you could improve would be this one. See the inline comments.
SELECT
t1.RoomID, t3.AuditType, t3.AuditDate, t3.AuditID, t1.CompleteStatus
INTO
#COMPLETE
FROM
(SELECT
RoomID,
COUNT(1) AS CompleteStatus
-- Use the above along with the WHERE clause below
-- so that you are aggregating fewer records and
-- avoiding a CASE statement. Remove this next line.
--SUM(CASE WHEN AuditType = 'Complete' THEN 1 ELSE 0 END) AS CompleteStatus
FROM
#AUDIT
WHERE
AuditType = 'Complete'
GROUP BY
RoomID) t1
INNER JOIN
#AUDIT t3 ON t1.RoomID = t3.RoomID
WHERE
t1.CompleteStatus = 0
OR t1.CompleteStatus > 1
Just a thought. Streamline your code and your solution. you are not effectively filtering your datasets smaller so you continue to query the entire tables which is taking a lot of your resources and your temp tables are becoming full copies of those columns without the indexes (PK, FK, ++??) on the original table to take advantage of. This by no means is a perfect solution but it is an idea of how you can consolidate your logic and reduce your overall data set. Give it a try and see if it performs better for you.
Note this will return the last audit record for any room that has either not had an audit completed or completed more than once.
;WITH cte AS (
SELECT
o.RoomId
,o.clientNum
,a.AuditId
,a.AuditDate
,a.AuditType
,NumOfAuditsComplete = SUM(CASE WHEN a.AuditType = 'Complete' THEN 1 ELSE 0 END) OVER (PARTITION BY o.RoomId)
,RowNum = ROW_NUMBER() OVER (PARTITION BY o.RoomId ORDER BY a.AuditDate DESC)
FROm
dbo.Rooms o
LEFT JOIN dbo.Audit a
ON o.RoomId = a.RoomId
WHERE
o.[Status] = 2
AND o.OrderType = 2
)
SELECT
oc.HotelId
,cte.RoomId
,cte.AuditId
,cte.AuditDate
,cte.AuditType
,cte.NumOfAuditsComplete
,cte.clientNum
,Complete_Error_Status = CASE WHEN cte.NumOfAuditsComplete > 1 THEN 'Complete More Than Once' ELSE 'Not Complete' END
FROM
cte
LEFT JOIN dbo.Hotels oc
ON cte.HotelId = oc.HotelId
LEFT JOIN dbo.clients c
ON cte.clientNum = c.clientNum
WHERE
cte.RowNum = 1
AND cte.NumOfAuditsComplete != 1
Also note I changed your
WHERE
o.[status] = '2'
AND o.orderType = '2'
TO
WHERE
o.[status] = 2
AND o.orderType = 2
to be numeric without the single quotes. If the data type is truely varchar add them back but when you query a numeric column as a varchar it will do data conversion and may not take advantage of indexes that you have built on the table.

Showing all values in Group By with inclusion of CASE

I have the following data
CREATE TABLE #Test
(
Severity NVARCHAR(50)
,WorkId INT
)
INSERT INTO #Test VALUES('High',1)
INSERT INTO #Test VALUES('Critical',2)
SELECT
CASE
WHEN Severity IN ('High','Critical') THEN 'Critical'
WHEN Severity IN ('Low','Medium') THEN 'Medium'
END AS 'Severity'
,COUNT(*) AS 'Total'
FROM #Test
GROUP BY
CASE
WHEN Severity IN ('High','Critical') THEN 'Critical'
WHEN Severity IN ('Low','Medium') THEN 'Medium'
END
This results in output -
Severity | Total
---------+-------
Critical | 2
I am expecting the following output -
Severity | Total
---------+-------
Critical | 2
Medium | 0
I have looked into the following two links which details a similar case but not same and am still unable to get the result -
http://ask.sqlservercentral.com/questions/47705/showing-null-values-as-well-in-group-by-in-sql.html
How to return empty groups in SQL GROUP BY clause
Any help or links?
Further update.
Having tried the solution below, the results are still not appearing. Pasting here the actual code wherein I would need to apply the logic
SELECT s.NewSeverity AS 'Severity'
,COUNT(WI.microsoft_vsts_common_severity) AS 'Total'
FROM ( VALUES
('Critical','I-High')
,('High','I-High')
,('Medium','I-Low')
,('Low','I-Low')
)s(OldSeverity,NewSeverity)
LEFT JOIN DimWorkItem WI (NOLOCK)
ON WI.microsoft_vsts_common_severity = s.OldSeverity
JOIN dbo.DimPerson P
ON p.personsk = WI.system_assignedto__personsk
JOIN DimTeamProject TP
ON WI.TeamProjectSK = TP.ProjectNodeSK
JOIN DimIteration Itr (NOLOCK)
ON Itr.IterationSK = WI.IterationSK
JOIN DimArea Ar (NOLOCK)
ON Ar.AreaSK = WI.AreaSK
WHERE TP.ProjectNodeName = 'ABC'
AND WI.System_WorkItemType = 'Bug'
AND WI.Microsoft_VSTS_CMMI_RootCause <> 'Change Request'
AND Itr.IterationPath LIKE '%\ABC\R1234\Test\IT%'
AND WI.System_State NOT IN ( 'Rejected', 'Closed' )
AND WI.System_RevisedDate = CONVERT(datetime, '9999', 126)
GROUP BY s.NewSeverity
In actual there are only two 'Low' items, hence the output I am getting is I-Low, 2 whereas I want even I-High to appear with 0 count.
The way I would go about this is to create your own table of values using a table value constructor:
SELECT OldSeverity, NewSeverity
FROM (VALUES
('Critical', 'Critical'),
('High', 'Critical'),
('Medium', 'Medium'),
('Low', 'Medium')
) s (OldSeverity, NewSeverity);
This gives a table you can select from, then left join to your existing table:
SELECT Severity = s.NewSeverity,
Total = COUNT(t.Severity)
FROM (VALUES
('Critical', 'Critical'),
('High', 'Critical'),
('Medium', 'Medium'),
('Low', 'Medium')
) s (OldSeverity, NewSeverity)
LEFT JOIN #Test t
ON t.Severity = s.OldSeverity
GROUP BY s.NewSeverity;
This will give the desired results.
Example on SQL Fiddle
EDIT
The problem you have with the way that you are implimenting the query, is that although you have immediately left joined to DimWorkItem you then inner join to subsequent tables and refer to columns in WorkItem in the where clause, which undoes your left join and turns it back into an inner join. You need to place your whole logic into a subquery, and left join to this:
SELECT s.NewSeverity AS 'Severity'
,COUNT(WI.microsoft_vsts_common_severity) AS 'Total'
FROM ( VALUES
('Critical','I-High')
,('High','I-High')
,('Medium','I-Low')
,('Low','I-Low')
)s(OldSeverity,NewSeverity)
LEFT JOIN
( SELECT wi.Severity
FROM DimWorkItem WI (NOLOCK)
JOIN dbo.DimPerson P
ON p.personsk = WI.system_assignedto__personsk
JOIN DimTeamProject TP
ON WI.TeamProjectSK = TP.ProjectNodeSK
JOIN DimIteration Itr (NOLOCK)
ON Itr.IterationSK = WI.IterationSK
JOIN DimArea Ar (NOLOCK)
ON Ar.AreaSK = WI.AreaSK
WHERE TP.ProjectNodeName = 'ABC'
AND WI.System_WorkItemType = 'Bug'
AND WI.Microsoft_VSTS_CMMI_RootCause <> 'Change Request'
AND Itr.IterationPath LIKE '%\ABC\R1234\Test\IT%'
AND WI.System_State NOT IN ( 'Rejected', 'Closed' )
AND WI.System_RevisedDate = CONVERT(datetime, '9999', 126)
) WI
ON WI.Severity = s.OldSeverity
GROUP BY s.NewSeverity;

SQL add Sum to existing query (Cannot perform an aggregate function on an expression containing an aggregate or a subquery.)

I have a existing working SQL query I would like to now GroupBy but am getting the error: Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
Explanation of my scenario:
My main table (dbo.DataLog) contains 3 columns, TimestampUTC, MeterTagId, Data.
Data typically comes in at 15 minute intervals and I have many meters (MeterTagId) for each
TimestampUTC. The Data column is a float and this is a totalised value. i.e. to get the actual value for a meter period I need to subtract the last value from the current one. Before now I have successfully been querying individual meters but now I am trying to group by time and show a sum/total of all meters for that time.
Original working non summed query:
SELECT
l.TimestampUTC
-- Get this value minus the last value
,(SELECT (l.[Data] -
( SELECT TOP 1 l2.Data
FROM [DataLog] l2
WHERE l2.MeterTagId = l.MeterTagId
AND l2.TimestampUTC < l.TimestampUTC
ORDER BY l2.TimestampUTC DESC)
)
) AS Actual_Value
FROM [dbo].[DataLog] l
INNER JOIN [dbo].MeterTags t on t.MeterTagId = l.MeterTagId
INNER JOIN [dbo].Meters m on m.MeterId = t.MeterId
INNER JOIN [dbo].GroupsMeters gm on gm.MeterId = m.MeterId
INNER JOIN [dbo].Groups g on g.GroupId = gm.GroupId
LEFT OUTER JOIN dbo.Units u on u.UnitId = t.UnitId
WHERE (#MeterId is null OR M.MeterId in (#MeterId))
AND (#MeterTagId is null OR t.MeterTagId in (#MeterTagId))
AND (#StartDate is null OR l.TimestampUTC >= #StartDate)
AND (#EndDate is null OR l.TimestampUTC <= #EndDate)
AND (#GroupId is null OR g.GroupId in (#GroupId))
.
My attempt to to get the summary:
SELECT
l.TimestampUTC
-- Get this value minus the last value
, (SELECT SUM(l.[Data] -
( SELECT TOP 1 l2.Data
FROM [DataLog] l2
WHERE l2.MeterTagId = l.MeterTagId
AND l2.TimestampUTC < l.TimestampUTC
ORDER BY l2.TimestampUTC DESC)
)
)AS Actual_Value
FROM [dbo].[DataLog] l
INNER JOIN [dbo].MeterTags t on t.MeterTagId = l.MeterTagId
INNER JOIN [dbo].Meters m on m.MeterId = t.MeterId
INNER JOIN [dbo].GroupsMeters gm on gm.MeterId = m.MeterId
INNER JOIN [dbo].Groups g on g.GroupId = gm.GroupId
LEFT OUTER JOIN dbo.Units u on u.UnitId = t.UnitId
WHERE (#MeterId is null OR M.MeterId in (#MeterId))
AND (#MeterTagId is null OR t.MeterTagId in (#MeterTagId))
AND (#StartDate is null OR l.TimestampUTC >= #StartDate)
AND (#EndDate is null OR l.TimestampUTC <= #EndDate)
AND (#GroupId is null OR g.GroupId in (#GroupId))
AND t.Name ='Real Energy Net'
GROUP BY l.TimestampUTC
I have read other posts on here but can't get my head around the logic required, I imagine/hope this is something sql dev's come across regularly? Thanks!
OK, I worked it out, it's simple really. Hopefully this explanation helps someone else with the same issue in the future.
SELECT
myTable.TimestampUTC
, SUM(myTable.Actual_Value) as [Actual Value]
FROM
(
--My original query
) AS myTable
GROUP BY myTable.TimestampUTC