Should be simple to do this but cannot make it work. Have also looked at other similar answers. This code generates a report. There are 3 primary categories: General Adjustments, Finance Charges, and Bad Debts. What I am trying to accomplish...
If these 3 columns are all zeros in a row, delete that row. That's it.
DECLARE #startdate DATETIME
DECLARE #lastdate DATETIME
SET #startdate = '20170701'
SET #lastdate = '20170731'
CREATE TABLE #a
(
ClientName VARCHAR(50),
JobName VARCHAR(50),
JobPartner VARCHAR(40),
[Date] DATETIME,
GenAdj MONEY,
FC MONEY,
BadDebt MONEY,
nomid INT
)
SELECT
C.searchname AS 'CLIENT NAME',
n.date AS 'DATE',
SUM(CASE WHEN NOMTYPEID=3 AND NOMSUBTYPEID=2 THEN TOTAL else 0 END) AS 'GENERAL ADJUSTMENTS',
SUM(CASE WHEN NOMTYPEID=3 AND NOMSUBTYPEID=1 THEN TOTAL else 0 END) AS 'FINANCE CHARGES',
SUM(CASE WHEN NOMTYPEID=3 AND NOMSUBTYPEID=0 THEN TOTAL else 0 END) AS 'BAD DEBTS',
sl.serviceline AS 'DEPARTMENT',
p.name AS 'PARTNER NAME'
FROM
tblNominal N
JOIN
tblNominalAccs A ON N.ContNominalID = A.NominalID
JOIN
tblclient C on N.clientid = C.clientid
LEFT JOIN
tbljob j ON n.jobid = j.JobID
LEFT JOIN
tblpartner p ON j.PartnerID = p.PartnerID
LEFT JOIN
tbljobtype jt ON j.jobtypeid = jt.jobtypeid
LEFT JOIN
tblserviceline sl ON j.servicelineid = sl.servicelineid
WHERE
Date >= #startdate AND DATE <= #LASTDATE
GROUP BY
C.searchname, n.date, sl.serviceline, p.name
ORDER BY
'CLIENT NAME' asc, 'FINANCE CHARGES' asc
DROP TABLE #a
I think I may be overthinking this. How can I delete the rows with all zeros?
Thank you for reading.
You need to use a HAVING clause after your GROUP BY but before your ORDER BY:
HAVING SUM(CASE WHEN NOMTYPEID=3 AND NOMSUBTYPEID=2 THEN TOTAL else 0 END) > 0
OR SUM(CASE WHEN NOMTYPEID=3 AND NOMSUBTYPEID=1 THEN TOTAL else 0 END) > 0
OR SUM(CASE WHEN NOMTYPEID=3 AND NOMSUBTYPEID=0 THEN TOTAL else 0 END) > 0
HAVING is kind of like a WHERE for group results.
Related
I have query that that references a dynamic calander table, it updates aged periods based on the current date. I am using this table in another query, it sum's sales value based on aged QTR's. These values will update as time passes and I can assign colmn names such as 'AGED1Q' but I would like to find a way to use the actual period name from the calander table. Any sugestions will be greatly appreciated.
Current query is below, I have added a few comment lines where I would like to make the changes. Thanks again
SELECT dbo.CUSTOMER_ORDER.CUSTOMER_ID AS CUST_ID,
SUM(CASE WHEN dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTRs_AGED = -4 THEN dbo.CUST_ORDER_LINE.TOTAL_AMT_ORDERED ELSE 0 END) AS '-4', --As MAX(dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTR) WHERE dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTRs_AGED = -4
SUM(CASE WHEN dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTRs_AGED = -3 THEN dbo.CUST_ORDER_LINE.TOTAL_AMT_ORDERED ELSE 0 END) AS '-3', --As MAX(dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTR) WHERE dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTRs_AGED = -3
SUM(CASE WHEN dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTRs_AGED = -2 THEN dbo.CUST_ORDER_LINE.TOTAL_AMT_ORDERED ELSE 0 END) AS '-2', --As MAX(dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTR) WHERE dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTRs_AGED = -2
SUM(CASE WHEN dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTRs_AGED = -1 THEN dbo.CUST_ORDER_LINE.TOTAL_AMT_ORDERED ELSE 0 END) AS '-1', --As MAX(dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTR) WHERE dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTRs_AGED = -1
SUM(CASE WHEN dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTRs_AGED IN(-4, -3, -2, -1) THEN dbo.CUST_ORDER_LINE.TOTAL_AMT_ORDERED ELSE 0 END) AS 'TOTAL'
FROM dbo.CUSTOMER_ORDER LEFT OUTER JOIN
dbo.UFC_Calander LEFT OUTER JOIN
dbo.UCC_CALENDAR_TODAY_BASED_AGING ON dbo.UFC_Calander.DAY = dbo.UCC_CALENDAR_TODAY_BASED_AGING.DATES ON
dbo.CUSTOMER_ORDER.ORDER_DATE = dbo.UFC_Calander.DAY LEFT OUTER JOIN
dbo.CUSTOMER ON dbo.CUSTOMER_ORDER.CUSTOMER_ID = dbo.CUSTOMER.ID RIGHT OUTER JOIN
dbo.PART RIGHT OUTER JOIN
dbo.CUST_ORDER_LINE ON dbo.PART.ID = dbo.CUST_ORDER_LINE.PART_ID ON dbo.CUSTOMER_ORDER.ID = dbo.CUST_ORDER_LINE.CUST_ORDER_ID
WHERE (dbo.CUSTOMER_ORDER.STATUS <> 'x') AND dbo.UCC_CALENDAR_TODAY_BASED_AGING.QTRs_AGED IN(-4, -3, -2, -1)
GROUP BY dbo.CUSTOMER_ORDER.CUSTOMER_ID
HAVING (dbo.CUSTOMER_ORDER.CUSTOMER_ID <> 'UNFOCO') AND (dbo.CUSTOMER_ORDER.CUSTOMER_ID <> 'QUOTE')
ORDER BY TOTAL DESC
Note: This is a follow[on,up] to this question and this question and this question.
The responses all moved me forward, but even that last one, although it improved matters, did not completely solve this issue.
This query:
select monthlysales, MemberNo from ReportingMonthlySales
where unit = 'Abuelos' and CYear = 2017 and cmonth = 3
...returns a bunch of rows, where the Monthly Sales total is $364,121.69
However, when I try to compartmentalize these monthly sales into four categories, although the sum of them all should be the same, the sum is actually astronomically "huger" - the following code returns the vastly inflated value of 23,924,211.30
24 millions of dollars is almost 70 times as much as the 364 thousand that is the actual sum total. Why is this "crazy" inflation occurring?
Here is the fancy pants but apparently bamboozled code:
declare #Unit varchar(30);
declare #Year int = 2017;
declare #Month int = 3;
declare #paramdate datetime;
set #paramdate = convert(datetime,convert(char(4),#Year)
+right('0'+convert(varchar(2),#month),2)
+'01')
IF OBJECT_ID('tempdb.dbo.#Units', 'U') IS NOT NULL
DROP TABLE #Units
select distinct unit
into #Units
from ReportingMonthlySales;
select
u.Unit
, New = sum(case when ccl.Subcategory = 'New' then rms.MonthlySales else 0 end)
, Assumed = sum(case when ccl.Subcategory = 'Assumed' then rms.MonthlySales else 0 end)
, Existing = sum(case when ccl.Subcategory = 'Existing' then rms.MonthlySales else 0 end)
, Organic = sum(case when ccl.Subcategory = 'Organic' then rms.MonthlySales else 0 end)
from #Units u
left join CustomerCategoryLog ccl
on u.Unit = ccl.Unit
and #paramdate >= ccl.begindate and
(#paramdate <= ccl.enddate OR ccl.enddate is null)
left join ReportingMonthlySales rms
on u.Unit = rms.Unit
and rms.cyear = #year
and rms.cmonth = #month
group by u.unit;
The two tables queried are:
CustomerCategoryLog
-------------------
MemberNo (VarChar)
Unit (VarChar)
Custno (VarChar)
Category (VarChar)
Subcategory (VarChar)
BeginDate (DateTime)
EndDate (DateTime)
ChangedBy (VarChar)
ChangedOn (DateTime)
ReportingMonthlySales
---------------------
AutoID (Int)
Unit (VarChar)
MemberNo (VarChar)
NumUnits (Int)
MonthlySales (Money)
CYear (Int)
Cmonth (Int)
CreateDate (DateTime)
Is there something faulty in the fancy-pants sql, or ... ?!?
I suspect the left joins and Or ccl.enddate is null generated a 1 to many
Perhaps a straight inner join will correct the inflation
select
u.Unit
, New = sum(case when ccl.Subcategory = 'New' then rms.MonthlySales else 0 end)
, Assumed = sum(case when ccl.Subcategory = 'Assumed' then rms.MonthlySales else 0 end)
, Existing = sum(case when ccl.Subcategory = 'Existing' then rms.MonthlySales else 0 end)
, Organic = sum(case when ccl.Subcategory = 'Organic' then rms.MonthlySales else 0 end)
from #Units u
join CustomerCategoryLog ccl on u.Unit = ccl.Unit and #paramdate >= ccl.begindate and #paramdate <= ccl.enddate
join ReportingMonthlySales rms on u.Unit = rms.Unit and rms.cyear = #year and rms.cmonth = #month
group by u.unit;
You are doing a join between the RMS table and these other tables. Your code assumes it will find one record for each record in the RMS table. This is not true. This is the cause of getting multiple rows reported and summed. I would think it is most likely that for a particular unit and #paramdate, there is multiple CCL entries.
i think this is causing the duplication
select distinct unit
into #Units
from ReportingMonthlySales;
you basically inserted the same data from the table and used at the left join..
try this updated script
SELECT
rms.Unit,
New = SUM(CASE
WHEN ccl.Subcategory = 'New' THEN rms.MonthlySales
ELSE 0
END),
Assumed = SUM(CASE
WHEN ccl.Subcategory = 'Assumed' THEN rms.MonthlySales
ELSE 0
END),
Existing = SUM(CASE
WHEN ccl.Subcategory = 'Existing' THEN rms.MonthlySales
ELSE 0
END),
Organic = SUM(CASE
WHEN ccl.Subcategory = 'Organic' THEN rms.MonthlySales
ELSE 0
END)
FROM ReportingMonthlySales rms
inner JOIN CustomerCategoryLog ccl
ON rms.Unit = ccl.Unit
where
AND #paramdate >= ccl.begindate
AND (#paramdate <= isnull(ccl.enddate,getdate())
)
AND
rms.cyear = #year
AND rms.cmonth = #month
GROUP BY rms.unit;
Your CustomerCategoryTable as what its name implies could have multiple records for different CustNo for the same UnitNo and that makes your first left join returns duplicate rows which will multiplies the monthly sales, and what I think is that there is no solution for your query except if you try to fix the schema itself for one simple information is that you are trying to find the monthly sales for each unit for it's different subcategorues and your ReportingMonthlySales table doesn't have any information regarding the subcategories.
I want to exclude the weekend and the holiday from my table:
for example in this picture I would like to exclude the date 19.01. and 10.01 from my table or it should show only 0 in 10.01.2016.
this is my code:
SELECT *
FROM (
Select intervaldate as Datum, tsystem.Name as Name,
SUM(case when Name = 'Maschine 1' then Units else 0 end) as Maschine1,
Sum(case when Name = 'Maschine 2' then Units else 0 end) as Maschine2,
Sum(case when Name = 'Maschine 3' then Units else 0 end) as Maschine3,
from Count inner join tsystem ON Count.systemid = tsystem.id
where IntervalDate BETWEEN #StartDateTime AND #EndDateTime
and tsystem.Name in ('M101','M102','M103','M104','M105','M107','M109','M110', 'M111', 'M113', 'M114', 'M115')
group by intervaldate, tsystem.Name
) as s
I think the best approach is create a table in your database and store all weekend and holidays dates then use that table to filter your query.
Something like this:
SELECT *
FROM (
Select intervaldate as Datum, tsystem.Name as Name,
SUM(case when Name = 'Maschine 1' then Units else 0 end) as Maschine1,
Sum(case when Name = 'Maschine 2' then Units else 0 end) as Maschine2,
Sum(case when Name = 'Maschine 3' then Units else 0 end) as Maschine3,
from Count inner join tsystem ON Count.systemid = tsystem.id
where IntervalDate BETWEEN #StartDateTime AND #EndDateTime
and IntervalDate NOT IN (select WeekendOrHolidayDate from MyWeekendAndHolidayTable)
and tsystem.Name in ('M101','M102','M103','M104','M105','M107','M109','M110', 'M111', 'M113', 'M114', 'M115')
group by intervaldate, tsystem.Name
) as s
The below query will exclude weekdays only. There is no way to produce holidays from SQL if you want to exclude also holidays you have to store it somewhere in your database.
SELECT *
FROM (
Select intervaldate as Datum, tsystem.Name as Name,
SUM(case when Name = 'Maschine 1' then Units else 0 end) as Maschine1,
Sum(case when Name = 'Maschine 2' then Units else 0 end) as Maschine2,
Sum(case when Name = 'Maschine 3' then Units else 0 end) as Maschine3,
from Count inner join tsystem ON Count.systemid = tsystem.id
where IntervalDate BETWEEN #StartDateTime AND #EndDateTime
and ((DATEPART(dw, IntervalDate) + ##DATEFIRST) % 7) NOT IN (0, 1)
and tsystem.Name in ('M101','M102','M103','M104','M105','M107','M109','M110', 'M111', 'M113', 'M114', 'M115')
group by intervaldate, tsystem.Name
) as s
Let me know if this helps you.
For excluding weekend...you can use date function and IIF condition. If week number is 7 or 1 then exclude in report...You can do this by right click on report properties and choose filter..
Right click the row group in your tablix and select Row Visibility. In the Change display options, select Show or hide based on an expression. In the expression, this should work:
=iif(CDate(Fields!Date.Value).DayOfWeek = DayOfWeek.Saturday, true, iif(CDate(Fields!Date.Value).DayOfWeek = DayOfWeek.Sunday, true, false))
If there's a ton of data, for performance reasons I'd recommend trimming these rows on the database side.
I am trying to get data for last 2 month ...but the query does not give perfect result....
SELECT DAY(table_A.PaymentDate) as date1 ,
(case when MONTH(table_A.PaymentDate) = MONTH(CURRENT_TIMESTAMP) - 1
then CAST(SUM(table_A.Total_Amount) AS INT)
else 0
end) AS last_month_CNT,
(case when MONTH(table_A.PaymentDate) = MONTH(CURRENT_TIMESTAMP)
then CAST(SUM(table_A.Total_Amount) As INT)
else 0
end) as This_month_CNT
FROM Tbl_Pan_Paymentdetails table_A
FULL OUTER JOIN Tbl_Pan_Paymentdetails table_B
ON table_A.PaymentDate=table_B.PaymentDate
WHERE YEAR(table_A.PaymentDate) = YEAR(CURRENT_TIMESTAMP)
AND
table_A.PaymentDate >= DATEADD(MONTH, -1, GETDATE())
GROUP BY
DAY(table_A.PaymentDate) ,MONTH(table_A.PaymentDate)
order by
DAY(table_A.PaymentDate);
Move the entire case expression inside the sum function and don't include the month in the group by. Also, the full outer join seems unnecessary so I removed it.
This should be what you are looking for:
SELECT
DAY(PaymentDate) as date1 ,
SUM(CASE WHEN MONTH(PaymentDate) = MONTH(CURRENT_TIMESTAMP)-1 THEN CAST(Total_Amount AS INT) ELSE 0 END) AS last_month_CNT,
SUM(CASE WHEN MONTH(PaymentDate) = MONTH(CURRENT_TIMESTAMP) THEN CAST(Total_Amount AS INT) ELSE 0 END) AS This_month_CNT
FROM Tbl_Pan_Paymentdetails
WHERE YEAR(PaymentDate) = YEAR(CURRENT_TIMESTAMP)
AND PaymentDate >= DATEADD(MONTH, -1, GETDATE())
GROUP BY DAY(PaymentDate)
ORDER BY DAY(PaymentDate);
I have the following SQL query
SELECT
[Date],
DATENAME(dw,[Date]) AS Day,
SUM(CASE WHEN ChargeCode IN (SELECT ChargeCode FROM tblChargeCodes WHERE Chargeable = 1) THEN Units ELSE 0 END) ChargeableTotal,
SUM(CASE WHEN ChargeCode IN (SELECT ChargeCode FROM tblChargeCodes WHERE Chargeable = 0) THEN Units ELSE 0 END) NotChargeableTotal,
SUM(Units) AS TotalUnits
FROM
tblTimesheetEntries
WHERE
UserID = 'PJW'
AND Date >= '2013-01-01'
GROUP BY
[Date]
ORDER BY
[Date] DESC;
But I get the error message:
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
Because I am using sub queries in the Case Else Summation.
How can I revise my query to get 2 x Sums of [Units] one for Chargeable = true, and one for Chargeable = false, even though the Chargeable field is in a different table to all the other information. The two tables are linked by ChargeCode which appears in both tblTimesheetEntries and tblChargeCodes.
Have you tried joining the tables on the chargeCode:
SELECT e.[Date],
DATENAME(dw,e.[Date]) AS Day,
SUM(CASE WHEN c.Chargeable = 1 THEN e.Units ELSE 0 END) ChargeableTotal,
SUM(CASE WHEN c.Chargeable = 0 THEN e.Units ELSE 0 END) NotChargeableTotal,
SUM(e.Units) AS TotalUnits
FROM tblTimesheetEntries e
LEFT JOIN tblChargeCodes c
on e.ChargeCode = c.ChargeCode
WHERE e.UserID = 'PJW'
AND e.Date >= '2013-01-01'
GROUP BY e.[Date]
ORDER BY e.[Date] DESC;