SQL - replace returned data with other data - sql

I am retrieving data using the SQL syntax below:
SELECT TOP 5 EventId, EventTime, DeviceName, Comment, Tenant, TenantName, Individual,
InetDb.dbo.Individuals.FirstName, InetDb.dbo.Individuals.LastName, InetDb.dbo.IndivImages.UserImage
FROM taclogdata.dbo.Event
LEFT JOIN InetDb.dbo.Tenants
ON taclogdata.dbo.Event.Tenant = InetDb.dbo.Tenants.TenantId
LEFT JOIN InetDb.dbo.Individuals
ON taclogdata.dbo.Event.Individual = InetDb.dbo.Individuals.IndivId
AND taclogdata.dbo.Event.Tenant = InetDb.dbo.Individuals.TenantNdx
LEFT JOIN InetDb.dbo.IndivImages
ON InetDb.dbo.Individuals.IndivId = InetDb.dbo.IndivImages.IndivNdx
AND InetDb.dbo.Individuals.TenantNdx = InetDb.dbo.IndivImages.TenantNdx
WHERE (taclogdata.dbo.Event.EventTime > DATEADD(hh, -3, GETDATE())AND taclogdata.dbo.Event.EventTime < GETDATE())
AND (taclogdata.dbo.Event.Comment='Reader entry' OR taclogdata.dbo.Event.Comment='Reader exit')
AND (taclogdata.dbo.Event.DeviceName = 'L9 1/4/1'
OR taclogdata.dbo.Event.DeviceName='L1 2/1/1-2 MainD'
OR taclogdata.dbo.Event.DeviceName='L1 2/1/3-4 MainD'
OR taclogdata.dbo.Event.DeviceName='L1 2/6/1-2 Stair'
OR taclogdata.dbo.Event.DeviceName='L1 2/2/1-2 FDT1')
ORDER BY taclogdata.dbo.Event.EventTime DESC
This code works fine, however I'm trying to simplify the results.
I'm trying to simplify what the query returns, by replacing the DeviceName value from e.g. L1 2/1/3-4 MainD to Main Door when the results are shown (not replace the actual data in the database)
How may I achieve this please ?
Thanks in advance,
J

try this use replace function
SELECT TOP 5 EventId, EventTime, replace(DeviceName,'L1 2/1/3-4 MainD','L1 2/1/3-4 Main Door') as DeviceName, Comment, Tenant, TenantName, Individual,
InetDb.dbo.Individuals.FirstName, InetDb.dbo.Individuals.LastName, InetDb.dbo.IndivImages.UserImage
FROM taclogdata.dbo.Event
LEFT JOIN InetDb.dbo.Tenants
ON taclogdata.dbo.Event.Tenant = InetDb.dbo.Tenants.TenantId
LEFT JOIN InetDb.dbo.Individuals
ON taclogdata.dbo.Event.Individual = InetDb.dbo.Individuals.IndivId
AND taclogdata.dbo.Event.Tenant = InetDb.dbo.Individuals.TenantNdx
LEFT JOIN InetDb.dbo.IndivImages
ON InetDb.dbo.Individuals.IndivId = InetDb.dbo.IndivImages.IndivNdx
AND InetDb.dbo.Individuals.TenantNdx = InetDb.dbo.IndivImages.TenantNdx
WHERE (taclogdata.dbo.Event.EventTime > DATEADD(hh, -3, GETDATE())AND taclogdata.dbo.Event.EventTime < GETDATE())
AND (taclogdata.dbo.Event.Comment='Reader entry' OR taclogdata.dbo.Event.Comment='Reader exit')
AND (taclogdata.dbo.Event.DeviceName = 'L9 1/4/1'
OR taclogdata.dbo.Event.DeviceName='L1 2/1/1-2 MainD'
OR taclogdata.dbo.Event.DeviceName='L1 2/1/3-4 MainD'
OR taclogdata.dbo.Event.DeviceName='L1 2/6/1-2 Stair'
OR taclogdata.dbo.Event.DeviceName='L1 2/2/1-2 FDT1')
ORDER BY taclogdata.dbo.Event.EventTime DESC

Here my suggestions:
If you can replace the data in your SELECT for example:
SELECT REPLACE(DeviceName,N'2/1/3-4 MainD',N'Main Door')
If you have many replacements, I would suggest to create a temporary table, join it and take the replacement from the temporary table.

The specific answer to your question is to use REPLACE() or a CASE statement. However, you should also change the WHERE clause to use IN and use table aliases so the code is easier to write and to read:
FROM taclogdata.dbo.Event e LEFT JOIN
InetDb.dbo.Tenants t
ON e.Tenant = t.TenantId LEFT JOIN
InetDb.dbo.Individuals i
ON e.Individual = i.IndivId AND e.Tenant = i.TenantNdx LEFT JOIN
InetDb.dbo.IndivImages ii
ON i.IndivId = ii.IndivNdx AND Ii.TenantNdx = ii.TenantNdx
WHERE (e.EventTime > DATEADD(hour, -3, GETDATE()) AND
e.EventTime < GETDATE()
) AND
e.Comment IN ('Reader entry', 'Reader exit') AND
e.DeviceName IN ('L9 1/4/1', 'L1 2/1/1-2 MainD', 'L1 2/1/3-4 MainD',
'L1 2/6/1-2 Stair', 'L1 2/2/1-2 FDT1'
)

Related

Not include this specific date in the query when using BETWEEN operator in SQL Server 2008

There is one specific date that I do not want to include in this which is "04/08/2020". I want to filter all the records from the beginning of the year till now but not 04/08/2020. How can I do that?
SELECT
dbo.PID_RespiratorFit.PTIDNum,
rtrim(acp.LastName) + ', ' + rtrim(acp.FirstName) AS Name,
acp.BadgeID AS ID,
dbo.Patient.PcFLD01 as Organization,
dbo.PID_RespiratorFit.Risk AS Exposure,
UPPER(dbo.PID_RespiratorFit.Type) AS Mask_Type,
dbo.PID_RespiratorFit.OHSNotes AS Comments,
dbo.PID_RespiratorFit.MedicallyClearedDate AS Medically_Cleared,
dbo.PID_RespiratorFit.TrainingCompletedDate,
dbo.PID_RespiratorFit.DateIssued AS N95_Fittest_Completed,
dbo.PID_RespiratorFit.Mask AS N95_respirator,
dbo.PID_RespiratorFit.PAPR,
dbo.PID_RespiratorFit.PaprFitTestDate AS PAPR_Fittest_Completed,
dbo.PID_RespiratorFit.Active,
DATEADD(year, 1, dbo.PID_RespiratorFit.MedicallyClearedDate) AS Compliant_Through
FROM dbo.PID_RespiratorFit LEFT JOIN
dbo.Patient ON dbo.PID_RespiratorFit.PTIDNum = dbo.Patient.PTIDNUM LEFT JOIN
dbo.aspnet_CustomProfile acp ON dbo.Patient.PGuid = acp.UserId
WHERE (dbo.PID_RespiratorFit.DateIssued BETWEEN '1-1-2020' AND Getdate())
Use standard date formats! Then:
WHERE dbo.PID_RespiratorFit.DateIssued BETWEEN '2020-01-01' AND Getdate() and
dbo.PID_RespiratorFit.DateIssued <> '2020-04-08' -- or is that 2020-08-04???
If the date is really a date/time, then use:
WHERE dbo.PID_RespiratorFit.DateIssued BETWEEN '2020-01-01' AND Getdate() and
CONVERT(DATE, dbo.PID_RespiratorFit.DateIssued) <> '2020-04-08' -- or is that 2020-08-04???
I also strongly recommend table aliases so the query is much easier to write and read. For example:
SELECT . . .
FROM dbo.PID_RespiratorFit rf LEFT JOIN
dbo.Patient p
ON rf.PTIDNum = p.PTIDNUM LEFT JOIN
dbo.aspnet_CustomProfile acp
ON p.PGuid = acp.UserId
WHERE rf.DateIssued BETWEEN '2020-01-01' AND Getdate() AND
CONVERT(DATE, rf.DateIssued) <> '2020-04-08' -- or is that 2020-08-04???
You can try the below - adding an extra condition
SELECT
dbo.PID_RespiratorFit.PTIDNum,
rtrim(acp.LastName) + ', ' + rtrim(acp.FirstName) AS Name,
acp.BadgeID AS ID,
dbo.Patient.PcFLD01 as Organization,
dbo.PID_RespiratorFit.Risk AS Exposure,
UPPER(dbo.PID_RespiratorFit.Type) AS Mask_Type,
dbo.PID_RespiratorFit.OHSNotes AS Comments,
dbo.PID_RespiratorFit.MedicallyClearedDate AS Medically_Cleared,
dbo.PID_RespiratorFit.TrainingCompletedDate,
dbo.PID_RespiratorFit.DateIssued AS N95_Fittest_Completed,
dbo.PID_RespiratorFit.Mask AS N95_respirator,
dbo.PID_RespiratorFit.PAPR,
dbo.PID_RespiratorFit.PaprFitTestDate AS PAPR_Fittest_Completed,
dbo.PID_RespiratorFit.Active,
DATEADD(year, 1, dbo.PID_RespiratorFit.MedicallyClearedDate) AS Compliant_Through
FROM dbo.PID_RespiratorFit LEFT JOIN
dbo.Patient ON dbo.PID_RespiratorFit.PTIDNum = dbo.Patient.PTIDNUM LEFT JOIN
dbo.aspnet_CustomProfile acp ON dbo.Patient.PGuid = acp.UserId
WHERE (dbo.PID_RespiratorFit.DateIssued BETWEEN '1-1-2020' AND Getdate())
AND cast(dbo.PID_RespiratorFit.DateIssued as date)<>'2020-04-08'

How could I join these queries together?

I have 2 queries. One includes a subquery and the other is a pretty basic query. I can't figure out how to combine them to return a table with name, workdate, minutes_inactive, and hoursworked.
I have the code below for what I have tried. The simple query is lines 1,2, and the last 5 lines. I also added a join clause (join punchclock p on p.servrepID = l.repid) to it.
Both these queries ran on their own so this is solely just the problem of combining them.
select
sr.sr_name as liaison, cast(date_created as date) workdate,
(count(date_created) * 4) as minutes_inactive,
(select
sr_name, cast(punchintime as date) as workdate,
round(sum(cast(datediff(minute,punchintime, punchouttime) as real) / 60), 2) as hoursworked,
count(*) as punches
from
(select
sr_name, punchintime = punchdatetime,
punchouttime = isnull((select top 1 pc2.punchdatetime
from punchclock pc2
where pc2.punchdatetime > pc.punchdatetime
and pc.servrepid = pc2.servrepid
and pc2.inout = 0
order by pc2.punchdatetime), getdate())
from
punchclock pc
join
servicereps sr on pc.servrepid = sr.servrepid
where
punchyear >= 2017 and pc.inout = 1
group by
sr_name, cast(punchintime as date)))
from
tbl_liga_popup_log l
join
servicereps sr on sr.servrepID = l.repid
join
punchclock p on p.servrepID = l.repid collate latin1_general_bin
group by
cast(l.date_created as date), sr.sr_name
I get this error:
Msg 102, Level 15, State 1, Line 19
Incorrect syntax near ')'
I keep getting this error but there are more errors if I adjust that part.
I don't know that we'll fix everything here, but there are a few issues with your query.
You have to alias your sub-query (technically a derived table, but whatever)
You have two froms in your outer query.
You have to join to the derived table.
Here's an crude example:
select
<some stuff>
from
(select col1 from table1) t1
inner join t2
on t1.col1 = t2.col2
The large error here is that you are placing queries in the select section (before the from). You can only do this if the query returns a single value. Else, you have to put your query in a parenthesis (you have done this) in the from section, give it an alias, and join it accordingly.
You also seem to be using group bys that are not needed anywhere. I can't see aggregation functions like sum().
My best bet is that you are looking for the following query:
select
sr_name as liaison
,cast(date_created as date) workdate
,count(distinct date_created) * 4 as minutes_inactive
,cast(punchintime as date) as workdate
,round(sum(cast(datediff(minute,punchintime,isnull(pc2_query.punchouttime,getdate())) as real) / 60), 2) as hoursworked
,count(*) as punches
from
punchclock pc
inner join servicereps sr on pc.servrepid = sr.servrepid
cross apply
(
select top 1 pc2.punchdatetime as punchouttime
from punchclock pc2
where pc2.punchdatetime > pc.punchdatetime
and pc.servrepid = pc2.servrepid
and pc2.inout = 0
order by pc2.punchdatetime
)q1
inner join tbl_liga_popup_log l on sr.servrepID = l.repid
where punchyear >= 2017 and pc.inout = 1

I need to add additional columns to my application that are not part of GROUPBY statement

I need some help with my SQL command. I have a VB.net application that uses few sql tables to get the final result. I need to add few additional columns from TableC into my application, but these columns are not part of GROUPBY function.
I tried to add simple select function to the code, but I always get the same error:
$"
SET NOCOUNT ON;
SELECT CONVERT(VARCHAR(10), r.PossibleDate, 120) as [Date],
**SELECT r.GStart as GStart,**
SUM(ISNULL(r.ElecCheckIn, 0)) as CheckIn,
SUM(ISNULL(r.ElecCheckOut, 0)) as CheckOut,
SUM(ISNULL(r.JPAmount, 0)) as AttAmountJP,
SUM(ISNULL(r.MeteredAttAmountCC, 0)) as AttAmountCC,
SUM(ISNULL(r.MeteredMachAmount, 0)) as MachAmount,
SUM(ISNULL(r.MeteredAttAmount, 0)) as AttAmount,
SUM(ISNULL(r.ElecCheckIn, 0) - ISNULL(r.ElecCheckOut, 0) - ISNULL(r.JPAmount, 0) - ISNULL(r.MeteredAttAmountCC, 0) - ISNULL(r.MeteredMachAmount, 0) - ISNULL(r.MeteredAttAmount, 0)) as NetWin
FROM dbo.CDS_TableA sm (NOLOCK)
INNER JOIN dbo.bb_tableB st (NOLOCK)
ON sm.TableB_Id=st.SlotB_Id
AND sm.TableBRevision=st.TabelBRevision
INNER JOIN dbo.TableC r (NOLOCK)
ON sm.TableA_ID=r.TableA_ID
AND r.PossibleDate BETWEEN '{dtStart.Value.ToString("yyyy-MM-dd")} 00:00:00' AND '{dtEnd.Value.ToString("yyyy-MM-dd")} 23:59:59'
AND r.Period_ID=4
INNER JOIN dbo.BB_TableD rh (NOLOCK)
ON sm.TableA_ID=rh.TableA_ID
AND r.PossibleDate=rh.PossibleDate
AND sm.Revision=rh.Revision
WHERE sm.OnFloorFlag = 1
AND sm.Calc_ID NOT IN (2,5)
GROUP BY r.PossibleDate
ORDER BY r.PossibleDate;
I always get an error that GStart is not contained in either an aggregate function or the GROUP BY clause.
Simply JOIN the aggregate level to unit level which can be facilitated with a CTE. Run this entire statement below including WITH clause.
WITH agg AS (
SELECT CONVERT(VARCHAR(10), r.PossibleDate, 120) as [Date],
SUM(ISNULL(r.ElecCheckIn, 0)) as CheckIn,
SUM(ISNULL(r.ElecCheckOut, 0)) as CheckOut,
SUM(ISNULL(r.JPAmount, 0)) as AttAmountJP,
SUM(ISNULL(r.MeteredAttAmountCC, 0)) as AttAmountCC,
SUM(ISNULL(r.MeteredMachAmount, 0)) as MachAmount,
SUM(ISNULL(r.MeteredAttAmount, 0)) as AttAmount,
SUM(ISNULL(r.ElecCheckIn, 0) -
ISNULL(r.ElecCheckOut, 0) -
ISNULL(r.JPAmount, 0) -
ISNULL(r.MeteredAttAmountCC, 0) -
ISNULL(r.MeteredMachAmount, 0) -
ISNULL(r.MeteredAttAmount, 0)) as NetWin
FROM dbo.CDS_TableA sm (NOLOCK)
INNER JOIN dbo.bb_tableB st (NOLOCK)
ON sm.TableB_Id =s t.SlotB_Id
AND sm.TableBRevision=st.TabelBRevision
INNER JOIN dbo.TableC r (NOLOCK)
ON sm.TableA_ID= r.TableA_ID
AND r.PossibleDate BETWEEN '{dtStart.Value.ToString("yyyy-MM-dd")} 00:00:00'
AND '{dtEnd.Value.ToString("yyyy-MM-dd")} 23:59:59'
AND r.Period_ID=4
INNER JOIN dbo.BB_TableD rh (NOLOCK)
ON sm.TableA_ID=rh.TableA_ID
AND r.PossibleDate=rh.PossibleDate
AND sm.Revision=rh.Revision
WHERE sm.OnFloorFlag = 1
AND sm.Calc_ID NOT IN (2,5)
GROUP BY r.PossibleDate
)
SELECT r.GStart as GStart, agg.* --- ADD OTHER r FIELDS
FROM dbo.TableC r
INNER JOIN agg ON CONVERT(VARCHAR(10), r.PossibleDate, 120) = agg.[Date]
ORDER BY r.PossibleDate
Aside: While I know nothing of vb.net, I do know running SQL at application layer and your concatenation of dates above should be parameterized values which is a programming industry best practice. See How do I create a parameterized SQL query? Why Should I? Also, use NOLOCK with caution.

SQL Server view optimization help (repeated subqueries, case when, and so on...)

I need some help optimizing a MSSQL view that is, honestly, a little too much complex for my knowledge.
The view is working good but I would like to rewrite it using less subqueries or a better structure in order to simplify it and use less server resources.
The main issue is a CASE WHEN with the same subquery repeated 4 times... I tried to understand if I can put it in a variable and use it for the CASE instead of repeating the query each time but it seems not possible to me...
Here's the query
SELECT dbo.MACCHINE.id_macchina, [...] dbo.VIEW_CANTIERI.indirizzo,
(SELECT TOP (1) data_fine
FROM dbo.MANUTENZIONI
WHERE (id_macchina = dbo.MACCHINE.id_macchina)
ORDER BY data_fine DESC)
AS ultima_manutenzione,
DATEDIFF(day,
(SELECT TOP (1) data_fine
FROM dbo.MANUTENZIONI AS MANUTENZIONI_1
WHERE (id_macchina = dbo.MACCHINE.id_macchina)
ORDER BY data_fine DESC), GETDATE())
AS data_diff,
(CASE WHEN
stato = 0
THEN 'GREY'
WHEN stato = 2
THEN 'BLACK'
WHEN stato = 1
THEN
(CASE WHEN
DATEDIFF(day,
(SELECT TOP (1) data_fine
FROM dbo.MANUTENZIONI AS MANUTENZIONI_1
WHERE (id_macchina = dbo.MACCHINE.id_macchina)
ORDER BY data_fine DESC), GETDATE()) >= 90
THEN 'RED'
WHEN
DATEDIFF(day,
(SELECT TOP (1) data_fine
FROM dbo.MANUTENZIONI AS MANUTENZIONI_1
WHERE (id_macchina = dbo.MACCHINE.id_macchina)
ORDER BY data_fine DESC), GETDATE()) >= 80
THEN 'ORANGE'
WHEN
DATEDIFF(day,
(SELECT TOP (1) data_fine
FROM dbo.MANUTENZIONI AS MANUTENZIONI_1
WHERE (id_macchina = dbo.MACCHINE.id_macchina)
ORDER BY data_fine DESC), GETDATE()) >= 60
THEN 'YELLOW'
WHEN
(SELECT TOP (1) data_fine
FROM dbo.MANUTENZIONI AS MANUTENZIONI_1
WHERE (id_macchina = dbo.MACCHINE.id_macchina)
ORDER BY data_fine DESC) IS NULL
THEN 'RED' ELSE 'GREEN'
END)
END)
AS colore FROM dbo.MACCHINE INNER JOIN
dbo.MACCHINE_MODELLI ON dbo.MACCHINE.id_modello = dbo.MACCHINE_MODELLI.id_modello INNER JOIN
dbo.MACCHINE_TIPOLOGIE ON dbo.MACCHINE_MODELLI.id_tipologia = dbo.MACCHINE_TIPOLOGIE.id_tipologia INNER JOIN
dbo.VIEW_CANTIERI ON dbo.MACCHINE.id_cantiere = dbo.VIEW_CANTIERI.id_cantiere INNER JOIN
dbo.MACCHINE_PRODUTTORI ON dbo.MACCHINE_MODELLI.id_produttore = dbo.MACCHINE_PRODUTTORI.id_produttore INNER JOIN
dbo.CLIENTI ON dbo.VIEW_CANTIERI.id_cliente = dbo.CLIENTI.id_cliente WHERE (dbo.MACCHINE._del = 'N')
Any suggestion is really appreciated, if you need more information about the db I will try to provide it...
I notice you are using TOP(1), so this must be 2005 or above. You can keep the result of the datediff in an OUTER APPLY subquery so that it is only evaluated once.
SELECT
M.id_macchina,
[...],
V.indirizzo,
MA.data_fine AS ultima_manutenzione,
MA.data_diff,
CASE
WHEN stato = 0 THEN 'GREY'
WHEN stato = 2 THEN 'BLACK'
WHEN stato = 1 THEN
CASE
WHEN MA.data_diff >= 90 THEN 'RED'
WHEN MA.data_diff >= 80 THEN 'ORANGE'
WHEN MA.data_diff >= 60 THEN 'YELLOW'
WHEN MA.data_fine IS NULL THEN 'RED'
ELSE 'GREEN'
END
END AS colore
FROM dbo.MACCHINE M
INNER JOIN dbo.MACCHINE_MODELLI I ON M.id_modello = I.id_modello
INNER JOIN dbo.MACCHINE_TIPOLOGIE T ON I.id_tipologia = T.id_tipologia
INNER JOIN dbo.VIEW_CANTIERI V ON M.id_cantiere = V.id_cantiere
INNER JOIN dbo.MACCHINE_PRODUTTORI P ON I.id_produttore = P.id_produttore
INNER JOIN dbo.CLIENTI C ON V.id_cliente = C.id_cliente
OUTER APPLY (SELECT TOP (1)
MA.data_fine,
DATEDIFF(day, MA.data_fine, GETDATE()) AS data_diff
FROM dbo.MANUTENZIONI AS MA
WHERE MA.id_macchina = M.id_macchina
ORDER BY MA.data_fine DESC) MA
WHERE M._del = 'N'
Apologies if you've done this already, but I would suggest using SHOWPLAN (ctrl+L), or performance tools if you have them. Confirm that it's really these CASE statements that are causing the issue - the bottleneck could be one of the joins for instance, a missing index, or stale statistics promoting a bad execution plan.
If the view is read from far more often than it is written to, or it doesn't need to have exactly up to date data (i.e. you could cache the results each day and read the view from last night's refresh), consider using an indexed view. This will cache the view as if it were a table, so the the operations (including both the CASE and the JOINs) are not performed every time you read from the table (having an index also speeds usage). Alternatively, if only recent data changes, you could try partitioning an indexed view on date.

Changing a SUM returned NULL to zero

I have a stored procedure as follows:
CREATE PROC [dbo].[Incidents]
(#SiteName varchar(200))
AS
SELECT
(
SELECT SUM(i.Logged)
FROM tbl_Sites s
INNER JOIN tbl_Incidents i
ON s.Location = i.Location
WHERE s.Sites = #SiteName AND i.[month] = DATEADD(mm, DATEDIFF(mm, 0, GetDate()) -1,0)
GROUP BY s.Sites
) AS LoggedIncidents
'tbl_Sites contains a list of reported on sites.
'tbl_Incidents contains a generated list of total incidents by site/date (monthly)
'If a site doesn't have any incidents that month it wont be listed.
The problem I'm having is that a site doesn't have any Incidents this month and as such i got a NULL value returned for that site when i run this proc, but i need to have a zero/0 returned to be used within a chart in SSRS.
I've tried using coalesce and isnull to no avail.
SELECT COALESCE(SUM(c.Logged,0))
SELECT SUM(ISNULL(c.Logged,0))
Is there a way to get this formatted correctly?
Cheers,
Lee
Put it outside:
SELECT COALESCE(
(
SELECT SUM(i.Logged)
FROM tbl_Sites s
INNER JOIN tbl_Incidents i
ON s.Location = i.Location
WHERE s.Sites = #SiteName AND i.[month] = DATEADD(mm, DATEDIFF(mm, 0, GetDate()) -1,0)
GROUP BY s.Sites
), 0) AS LoggedIncidents
If you are returning multiple rows, change INNER JOIN to LEFT JOIN
SELECT COALESCE(SUM(i.Logged),0)
FROM tbl_Sites s
LEFT JOIN tbl_Incidents i
ON s.Location = i.Location
WHERE s.Sites = #SiteName AND i.[month] = DATEADD(mm, DATEDIFF(mm, 0, GetDate()) -1,0)
GROUP BY s.Sites
By the way, don't put any function or expression inside aggregate functions if it's not warranted, e.g. don't put ISNULL, COALESCE inside of SUM, using function/expression inside aggregation cripples performance, the query will be executed with table scan
You'll have to use ISNULL like this -
ISNULL(SUM(c.Logged), 0)
Or, as Michael said, you can use a Left Outer Join.
I encountered this problem in Oracle.
Oracle does not have an ISNULL() function. However, we can use the NVL() function to achieve the same result:
NVL(SUM(c.Logged), 0)
The easiest, and most readable, way I've found to accomplish this is through:
CREATE PROC [dbo].[Incidents]
(#SiteName varchar(200))
AS
SELECT SUM(COALESCE(i.Logged, 0)) AS LoggedIncidents
FROM tbl_Sites s
INNER JOIN tbl_Incidents i
ON s.Location = i.Location
WHERE s.Sites = #SiteName
AND i.[month] = DATEADD(mm, DATEDIFF(mm, 0, GetDate()) -1,0)
GROUP BY s.Sites
You could wrap the SELECT in another SELECT like so:
CREATE PROC [dbo].[Incidents]
(#SiteName varchar(200))
AS
SELECT COALESCE(TotalIncidents ,0)
FROM (
SELECT
(
SELECT SUM(i.Logged) as TotalIncidents
FROM tbl_Sites s
INNER JOIN tbl_Incidents i
ON s.Location = i.Location
WHERE s.Sites = #SiteName AND i.[month] = DATEADD(mm, DATEDIFF(mm, 0, GetDate()) -1,0)
GROUP BY s.Sites
) AS LoggedIncidents
)
Just ran into this problem, Kirtan's solution worked for me well, but the syntax was a little off. I did like this:
ISNULL(SUM(c.Logged), 0)
Post helped me solve my problem though so thanks to all.
The code you've posted above
SELECT SUM(ISNULL(c.Logged,0))
would not work due to wrong order
what would work is the following
SELECT ISNULL(SUM(c.Logged),0)
It evaulates the expression SUM then if it returns NULL it is replaced with 0.