removing nulls in case statement - sql

I am trying to return the current Monday along with previous monday's data. I want to roll up my nulls or 0000 to have one record return.
select
da.Customer,
sum(case
when DAteadd(wk, datediff(wk, 0, Getdate()), 1) = d.FullDate
then (da.[USD - Balance])
else 0
end) as MondayofCurrentWeek,
sum(case
when DAteadd(wk, datediff(wk, 0, Getdate() - 7), 1) = d.FullDate
then (da.[USD - Balance])
else 0
end) as PreviousMonday
from
Dataset_DemandArchive da
inner join
Dimdate d on d.DateNameUS = da.CREDAT_0
where
da.CREDAT_0 in (dateadd(wk, datediff(wk, 0, Getdate()), 1),
dateadd(wk, datediff(wk, 0, Getdate() - 7), 1))
group by
Customer, FullDate
order by
1

Why not just use window functions?
select da.*
from (select da.Customer, d.FullDate,
sum(da.[USD - Balance]) as MondayCurrentWeek
lag(sum(da.[USD - Balance]), 7) over (partition by da.Customer order by d.FullDate)
from Dataset_DemandArchive da join
Dimdate d
on d.DateNameUS = da.CREDAT_0
group by Customer, FullDate
) da
where da.CREDAT_0 = dateadd(week, datediff(week, 0, Getdate()), 1)

Related

I want to select last hour results

SELECT DISTINCT
ip.IPAddress,
CONVERT(varchar, dan.AuditDate, 100) AS Date,
ip.AuditAction,ip.Username,
(CASE
WHEN CONCAT(k.FirstName, ' ', k.LastName) IS NULL OR CONCAT(k.FirstName, ' ', k.LastName) = ' '
THEN k.Name
ELSE CONCAT(k.FirstName, ' ', k.LastName)
END) AS 'Name'
FROM
IPAddress ip
INNER JOIN
user k ON k.ID = ip.PerformerID
INNER JOIN
audit dan ON ip.IPAddress = dan.Value1
AND ip.Date = CAST(dan.AuditDate AS Date)
AND ip.AuditAction = dan.AuditStr
AND ip.PerformerID = dan.PerformerID
INNER JOIN
LoginMoreOne n ON n.LUsername = ip.Username
AND n.LUsername IS NOT NULL
WHERE
LEN(ip.IPAddress) > 8
AND dan.AuditDate > DATEADD(HOUR, DATEDIFF(hour, 0, DATEADD(mi, 30, GETDATE())), 0)
GROUP BY
ip.IPAddress, ip.Date, ip.AuditAction,
ip.Username, ip.PerformerID,
k.FirstName, k.LastName, k.Name,
CAST(dan.AuditDate AS Date), dan.AuditDate
For example if I execute this query at 2.30pm, I want the result from 1pm to 2pm, or if i execute this query at 3.10pm, I want the result from 2pm-3pm, and so on, How do I edit my where statement to be able get the desired result
The expression dateadd(hour, datediff(hour, 0, getdate()), 0) will gives you date & time at current hour, with minutes, seconds = 0
-1 gives you the previous hour with 0 mins, 0 secs
AuditDate >= dateadd(hour, datediff(hour, 0, getdate()) - 1, 0)
and AuditDate < dateadd(hour, datediff(hour, 0, getdate()), 0)
Instead
dan.AuditDate > DATEADD(HOUR, datediff(hour, 0, dateadd(mi, 30, GETDATE())), 0)
Use:
dan.AuditDate > DATEADD(HH, -1.5, GETDATE()) AND dan.AuditDate <= DATEADD(HH,-0.5, GETDATE())

How to get value 0 if the result of sql select except statement return no records?

I have a problem with the SQL Except statement, in my case, I select two columns and one column can have values and the others cannot have because the count of the first SQL statement equals the count of the second SQL after the except statement.
Result that I got :
GroupId absences
1 3
Expected result
GroupId absences
1 3
2 0
How can I do in this case?
select
groupId,
(case when groupId = null then 0 else COUNT(*) end) as absence
from (
select
groupId,
COUNT(*) as absences1
from (
select distinct
MONTh,
DAY,
e.groupId
from employee_c c,
holiday hl,
employee e,
groups,
Get_Calendar_Date(
DATEADD(MONTH, DATEDIFF(MONTH, 0, CAST(DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0) AS datetime)) + #Month - 1, 0),
DATEADD(MONTH, DATEDIFF(MONTH, -1, CAST(DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0) AS datetime)) + #Month-1, -1)
)
where DATENAME(DD, Weekday) IN (
select WorkingdayId+1
from timetable s,
groups ds,
grouptime de
where dd.groupId = ds.groupId
and dd.groupId = de.groupId
and s.timetableId = de.timetableId
and de.groupId = ds.groupdId)
and DATEPART(MM,hl.startDate) = #Month
and c.isActive=1
except
(select Month,
Day,
d.departmentId
from department d,
Get_Calendar_Date(
DATEADD(MONTH, DATEDIFF(MONTH, 0, CAST(DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0) AS datetime)) + #Month - 1, 0),
DATEADD(MONTH, DATEDIFF(MONTH, -1, CAST(DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0) AS datetime)) + #Month - 1, -1)
),
holiday hle,
employee_c c,
employee e
where datepart(MM,hle.startDate) = #Month
and cast(Date as date) between hle.startDate and hle.endDate
and c.isActive=1
and d.groupId =e.groupId
and c.employeeId=e.employeeId
and c.isActive=1
)
) sc
group by Month,Day,groupId
) s
group by groupId

Subtracting one month from a date but making sure it is the first business day of that month

I need to subtract one month from a date called ArchiveDate but I want the first business day of that month. For example if my ArchiveDate is 9/2/2018 I would like to have 8/1/2019.
This is what I have:
DECLARE #ArchiveDate date = '9/2/2019'
SELECT ArchiveDate = DATEADD(day,
CASE WHEN
DATEPART(weekday, DATEADD(MONTH, -1, #ArchiveDate)) = 1
THEN 1
WHEN DATEPART(weekday, DATEADD(MONTH, -1, #ArchiveDate)) = 7 THEN 2
ELSE 0
END
, DATEADD(MONTH, -1, #ArchiveDate))
What I get from this is 8/2/2019 but as you can see I want 8/1/2019.
SELECT
CASE
WHEN DATENAME(WEEKDAY, DATEADD(mm, DATEDIFF(mm, 0, #ArchiveDate) - 1, 0)) = 'Saturday'
THEN DATEADD(mm, DATEDIFF(mm, 0, #ArchiveDate) - 1, 0) + 2
WHEN DATENAME(WEEKDAY, DATEADD(mm, DATEDIFF(mm, 0, #ArchiveDate) - 1, 0)) = 'Sunday'
THEN DATEADD(mm, DATEDIFF(mm, 0, #ArchiveDate) - 1, 0) + 1
ELSE
DATEADD(mm, DATEDIFF(mm, 0, #ArchiveDate) - 1, 0)
END
This will return the first BUSINESS DAY of the previous month.
you can use eomonth along with your logic to get first day of previous month as below:
DECLARE #ArchiveDate date = '9/2/2019'
select dateadd(day, 1, eomonth(dateadd(month, -2, #ArchiveDate)));
You can use EOMONTH with DATEADD():
SELECT DATEADD(DAY, 1, EOMONTH(#ArchiveDate, -2)) AS ArchiveDate

SQL to exclude NULL or value 0

I have below SQL code,
SELECT s.[CusNo] Supp,
RTRIM(CAST(s.[Customer] AS VARCHAR(50))) AS Name,
s.[ConNo] Con,
RTRIM(CAST(s.[ConN] AS VARCHAR(50))) AS ConN,
sum(case when s.Date between convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) - 1) and convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) + 5)
then s.SELL else 0 end) ActualSales
FROM [dbo].[Reports] s
WHERE s.BOX = 2
AND s.SELL <> 0
GROUP BY s.[CusNo], s.[Customer], s.ConNo, s.ConN
When I execute the above query, I am getting all the values (including 0 values) in ActualSales column.
How to remove the rows which as value 0 please?
Use having clause
SELECT s.[CusNo] Supp,
RTRIM(CAST(s.[Customer] AS VARCHAR(50)) ) AS Name,
s.[ConNo] Con,
RTRIM(CAST(s.[ConN] AS VARCHAR(50)) ) AS ConN,
sum(case when s.Date between convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) - 1) and convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) + 5)
then s.SELL else 0 end) ActualSales
FROM [dbo].[Reports] s
WHERE s.BOX = 2 and s.SELL <> 0
GROUP BY s.[CusNo], s.[Customer], s.ConNo, s.ConN
having sum(case when s.Date between convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) - 1) and convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) + 5)
then s.SELL else 0 end)<>0
OR you can use subquery
select * from
(
SELECT s.[CusNo] Supp,
RTRIM(CAST(s.[Customer] AS VARCHAR(50)) ) AS Name,
s.[ConNo] Con,
RTRIM(CAST(s.[ConN] AS VARCHAR(50)) ) AS ConN,
sum(case when s.Date between convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) - 1) and convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) + 5)
then s.SELL else 0 end) ActualSales
FROM [dbo].[Reports] s
WHERE s.BOX = 2 and s.SELL <> 0
GROUP BY s.[CusNo], s.[Customer], s.ConNo, s.ConN
)A where ActualSales<>0
I think you might get what you want by moving the case condition to the where clause:
SELECT s.[CusNo] as Supp,
RTRIM(CAST(s.[Customer] AS VARCHAR(50)) ) AS Name,
s.[ConNo] as Con,
RTRIM(CAST(s.[ConN] AS VARCHAR(50)) ) AS ConN,
SUM(s.SELL) as ActualSales
FROM [dbo].[Reports] s
WHERE s.BOX = 2 AND s.SELL <> 0 AND
s.Date BETWEEN convert(date, dateadd(wk, datediff(week, 0, getdate()) - 1, 0) - 1) and
convert(date,dateadd(wk, datediff(week, 0, getdate()) - 1, 0) + 5)
GROUP BY s.[CusNo], s.[Customer], s.ConNo, s.ConN;
It is possibly that ActualSales could still be 0 (if Sales could be negative. In that case, you would want a HAVING clause: HAVING SUM(Sales) <> 0.
Because this approach filters before aggregation, it might also benefit performance.

Select top 50 rows in sql server

I have below T-SQL code used in SQL Server 2014.
This code produces 1000s of rows. But i need only top 50 rows (from Supplier Column) from this.
In the below code, if I use SELECT Top 50 s.[CusNo] Supplier then I am not getting desired results.
What changes needs to be done in the below code in order to get only Top 50 rows (of Supplier column) with out any change in the existing result.
SELECT s.[CusNo] Supplier,
RTRIM(CAST(s.[Customer] AS VARCHAR(50)) ) AS Name,
s.[ConcessionNo] Concession,
RTRIM(CAST(s.[ConcessionName] AS VARCHAR(50)) ) AS ConcessionName,
sum(case when s.Date between convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) - 1) and convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) + 5)
then s.SELLINC else 0 end) ActualSales,
sum(case when s.Date between convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) -1 /* On 14/Feb/2021 modify +6 to -1 */) and convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) + 5 /* On 14/Feb/2021 modify +12 to +5 */)
then s.SELLINC else 0 end) LastYrVariance,
(sum(case when s.Date between convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) - 1) and convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) + 5) then s.SELLINC else 0 end))-
(sum(case when s.Date between convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) -1 /* On 14/Feb/2021 modify +6 to -1 */) and convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) + 5 /* On 14/Feb/2021 modify +12 to +5 */) then s.SELLINC else 0 end)) LastYrVariancePounds,
(IsNull(sum(case when s.Date between convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) - 1) and convert(date,dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) + 5)
then s.SELLINC else 0 end)-sum(case when s.Date between convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) -1 /* On 14/Feb/2021 modify +6 to -1 */) and convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) + 5 /* On 14/Feb/2021 modify +12 to +5 */)
then s.SELLINC else 0 end),0)/NullIf(sum(case when s.Date between convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) -1 /* On 14/Feb/2021 modify +6 to -1 */) and convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) + 5 /* On 14/Feb/2021 modify +12 to +5 */)
then s.SELLINC else 0 end),0))*100 LastYrVariancePercentage,
sum(case when s.Date
BETWEEN
convert(varchar(10), DATEADD(day, DATEDIFF(day, '19000107', DATEADD(month, DATEDIFF(MONTH, 0, CONVERT(date, CONVERT(VARCHAR(4), (CASE WHEN MONTH(GetDate()) = 1 THEN CONVERT(VARCHAR(4), GetDate(), 112) - 1 ELSE CONVERT(VARCHAR(4), GetDate(), 112) END), 112) + '0101')), 30)) / 7 * 7, '19000107'), 120)
AND
Convert(date, dateadd(wk, datediff(wk, 0, GETDATE()) - 1, 0) + 5)
then s.SELLINC else 0 end) YrToDateActual,
sum(case when s.Date
BETWEEN
convert(varchar(10), DATEADD(day, DATEDIFF(day, '19000107', DATEADD(month, DATEDIFF(MONTH, 0, CONVERT(date, CONVERT(VARCHAR(4), (CASE WHEN MONTH(DATEADD(year,-1,GetDate())) = 1 THEN CONVERT(VARCHAR(4), DATEADD(year,-1,GetDate()), 112) - 1 ELSE CONVERT(VARCHAR(4), DATEADD(year,-1,GetDate()), 112) END), 112) + '0101')), 30)) / 7 * 7, '19000107'), 120)
AND
convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) + 5 /* On 14/Feb/2021 modify +12 to +5 */)
then s.SELLINC else 0 end) LastYrToDateActual,
(sum(case when s.Date
BETWEEN
convert(varchar(10), DATEADD(day, DATEDIFF(day, '19000107', DATEADD(month, DATEDIFF(MONTH, 0, CONVERT(date, CONVERT(VARCHAR(4), (CASE WHEN MONTH(GetDate()) = 1 THEN CONVERT(VARCHAR(4), GetDate(), 112) - 1 ELSE CONVERT(VARCHAR(4), GetDate(), 112) END), 112) + '0101')), 30)) / 7 * 7, '19000107'), 120)
AND
Convert(date, dateadd(wk, datediff(wk, 0, GETDATE()) - 1, 0) + 5)
then s.SELLINC else 0 end))
-
(sum(case when s.Date
BETWEEN
convert(varchar(10), DATEADD(day, DATEDIFF(day, '19000107', DATEADD(month, DATEDIFF(MONTH, 0, CONVERT(date, CONVERT(VARCHAR(4), (CASE WHEN MONTH(DATEADD(year,-1,GetDate())) = 1 THEN CONVERT(VARCHAR(4), DATEADD(year,-1,GetDate()), 112) - 1 ELSE CONVERT(VARCHAR(4), DATEADD(year,-1,GetDate()), 112) END), 112) + '0101')), 30)) / 7 * 7, '19000107'), 120)
AND
convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) + 5 /* On 14/Feb/2021 modify +12 to +5 */)
then s.SELLINC else 0 end)) YrToDateVariancePounds,
((IsNull
(
(sum(case when s.Date
BETWEEN
convert(varchar(10), DATEADD(day, DATEDIFF(day, '19000107', DATEADD(month, DATEDIFF(MONTH, 0, CONVERT(date, CONVERT(VARCHAR(4), (CASE WHEN MONTH(GetDate()) = 1 THEN CONVERT(VARCHAR(4), GetDate(), 112) - 1 ELSE CONVERT(VARCHAR(4), GetDate(), 112) END), 112) + '0101')), 30)) / 7 * 7, '19000107'), 120)
AND
Convert(date, dateadd(wk, datediff(wk, 0, GETDATE()) - 1, 0) + 5)
then s.SELLINC else 0 end))
-
(sum(case when s.Date
BETWEEN
convert(varchar(10), DATEADD(day, DATEDIFF(day, '19000107', DATEADD(month, DATEDIFF(MONTH, 0, CONVERT(date, CONVERT(VARCHAR(4), (CASE WHEN MONTH(DATEADD(year,-1,GetDate())) = 1 THEN CONVERT(VARCHAR(4), DATEADD(year,-1,GetDate()), 112) - 1 ELSE CONVERT(VARCHAR(4), DATEADD(year,-1,GetDate()), 112) END), 112) + '0101')), 30)) / 7 * 7, '19000107'), 120)
AND
convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) + 5 /* On 14/Feb/2021 modify +12 to +5 */)
then s.SELLINC else 0 end))
,0)
)
/
(NullIf
(
sum(case when s.Date
BETWEEN
convert(varchar(10), DATEADD(day, DATEDIFF(day, '19000107', DATEADD(month, DATEDIFF(MONTH, 0, CONVERT(date, CONVERT(VARCHAR(4), (CASE WHEN MONTH(DATEADD(year,-1,GetDate())) = 1 THEN CONVERT(VARCHAR(4), DATEADD(year,-1,GetDate()), 112) - 1 ELSE CONVERT(VARCHAR(4), DATEADD(year,-1,GetDate()), 112) END), 112) + '0101')), 30)) / 7 * 7, '19000107'), 120)
AND
convert(date,dateadd(wk, datediff(wk, 0, dateadd(YEAR, - 1, getdate())) - 1, 0) + 5 /* On 14/Feb/2021 modify +12 to +5 */)
then s.SELLINC else 0 end)
,0)))*100 LastYrToDateVariancePercentage
FROM [dbo].[CustomerReports] s
WHERE s.BRN = 1 or s.BRN = 2 or s.BRN = 3 or s.BRN = 4 or s.BRN = 5 or s.SELLINC is null or s.SELLINC = '0'
GROUP BY s.[CusNo], s.[Customer], s.ConcessionNo, s.ConcessionName
order by YrToDateActual desc
When I run this Query In SSRS I get below results (Which is Correct). But displays all the data.
if I use SELECT Top 50 s.[CusNo] Supplier (Rest of the code is same) then I am getting the below,
So please see the highlighted section in both the images. When I add Top 50 in SQL code then few rows (in 3rd column ) which were present in 1st image is not present in 2nd image.
Try this:
With cte as (**your long query goes here**)
Select Top(50) * From cte
The sort order in your query is by YrToDateActual desc, so the TOP 50 is giving you the highest 50 YrToDateActual amounts. Your SSRS report is grouping by Supplier number and name, but doesn't look to be sorting by either of these columns, so I'm guessing that the order of these suppliers is somewhat random in the SSRS output. In this case I don't think you're ever going to be able to get the first 50 rows of your original SSRS output. The best you could do would be to also sort your SSRS output (e.g. by Supplier number) and then add this sort into your query (order by Supplier, YrToDateActual desc). Adding the TOP 50 into your query would cut off your new sorted SSRS output after the first 50 results.
What do you want to see in the report? Do you want to see the top 50 suppliers based on their total value (e.g. Actual £ Total) and then all the Concessions (as per your first screenshot) ?
If so, you will need to rank the suppliers by their total and select any that are rank 50 or below.
Here's a very simplified example that might help. In this I've used SUM() OVER() rather than using GROUP BY but this means you might want to change the SELECT to SELECT DISTINCT depending on you needs as you will get lots of duplicate rows. Obviously it's not got your lengthy case statements in but you should be able to adapt it easily.
SELECT * FROM
(
SELECT
x.*
, DENSE_RANK() OVER(ORDER BY SupplierTotal DESC) as SupplierRank
, DENSE_RANK() OVER(PARTITION BY SupplierID ORDER BY ConcessionTotal DESC) as ConcessionRank
FROM
( SELECT DISTINCT
SupplierID, ConcessionID, MyOtherRequiredColumns,
SUM(myValue) OVER(PARTITION BY SupplierID) AS SupplierTotal,
SUM(myValue) OVER(PARTITION BY SupplierID, ConcessionID) AS ConcessionTotal
FROM MyTable
) x
) z
WHERE SupplierRank <= 50
This will also rank the concessions within supplier which might be useful..
You will also have to change you report where you have summed the values up (e.g. 99,389 in Actual £ column). Instead of summing the rows below, change the expression to be =FIRST(Fields!SupplierTotal.Value)