Where clause within Case Statement - sql

I need to drill into detail on to an existing report which shows me the total profitability per customer, per month on a telecoms company.
The company sells calls, service charges and has discounts.
This is the query that I'm using, using one customer in particular:
SELECT
custumer_name,
ISNULL(SUM(CASE CONVERT(VARCHAR(10), month_end, 103)
WHEN '31/10/2016'
THEN totcall + isnull(totrec, 0) - discount
ELSE 0
END), 0) AS '31/10/2016',
SUM(totcall) AS 'Total Calls',
SUM(totrec) AS 'Total Rec',
SUM(discount) AS 'Discounts'
FROM
total_sales
INNER JOIN
customer_details ON billingaddress = customer_details .siteid
INNER JOIN
sales_month d ON total_sales.periodid = d.monthid
INNER JOIN
customer b ON customer_details .id = b.id AND b.is_customer = 1
WHERE
b.custumer_name = '2
GROUP BY
b.custumer_name
ORDER BY
b.custumer_name ASC
This is bringing back the correct total however when I need to show the drilldown of the total on calls, rec & discounts it is showing me the actual sum of every months' data which is stored on that table.
I'm not sure how can I get the last 3 columns to itemise the total without specifying the actual month (as the report has columns for the last 12 months of data.
Please help?
Thank you!
PS. The DB is a SQL Server 2008

Related

SQL help to display no. of openings for all branches for each month of a year

Hi I need to generate a SSRS report to show how many centers got opened for each month in a calendar year under each branch. report will have 13 columns, first column being all the branches in each row and remaining 12 columns will have months of an year as header. I'm trying to get a result of each branch having no. of openings per month, so I can feed SSRS to display in tabular format. If a branch doesnt have any openings for any month, I need to display 0.
Branch table
=============
Branchid
Branchname
CenterOpen table
================
CenterOpenID
BranchID
CenterOpenDate
below is the SQL I had written
WITH months(MonthNumber) AS (
SELECT
1
UNION ALL
SELECT
MonthNumber + 1
FROM
months
WHERE
MonthNumber < 12
),
cteBranch(BranchID, BranchName, TargetOpenDate, Month, Count) as (
SELECT
B.BranchID,
B.BranchName,
CS.TargetOpenDate,
MONTH(CS.TargetOpenDate) as Month,
count(Month(CS.TargetOpenDate)) as Count
FROM
Branch B
left join goal.CenterOpenSchedule CS ON CS.BranchID = B.BranchID
GROUP BY
B.BranchID,
B.BranchName,
CS.TargetOpenDate,
MONTH(CS.TargetOpenDate)
)
select
*
from
months
cross join cteBranch
order by
BranchID asc,
MonthNumber asc
If I use cross join, months are repeating for each branch, how to resolve this? your help is highly appreciated.
Not sure which database you are on.
There are different ways to extract month/year from date.
Based on your example SQL, I'm going to use MONTH()
select branchName,
count(case when month(centerOpenDate) = 1 then branchId end) Jan_Count
...
...
count(case when month(centerOpenDate) = 12 then branchId end) Dec_Count
from Branch b
join CenterOpen co
on (b.BranchId = co.BranchId)
where year(centerOpenDate) = <your year filter>
group by branchName
This will take care of your below requirements:
" first column being all the branches in each row and remaining 12 columns will have months of an year as header."
and also -
"If a branch doesnt have any openings for any month, I need to display 0."
Your question is not explicit, but you seem to want a single year -- so you need to filter on the year.
The rest is basically conditional aggregation:
select b.branchName,
sum(case when month(co.centerOpenDate) = 1 then 1 else 0 end) as jan,
sum(case when month(co.centerOpenDate) = 2 then 1 else 0 end) as feb,
. . .
sum(case when month(co.centerOpenDate) = 12 then 1 else 0 end) as dec
from Branch b join
CenterOpen co
on b.BranchId = co.BranchId
where year(co.centerOpenDate) = #year
group by b.branchName

Somar um valor total e retornar muitas linhas

I have two tables (order header and order lines). I want to add the order lines, group by month and year, but it brings me all the rows of all the orders. Have you any way to sum it up?
This is probably because I'm doing one calculation per line.
I need to do it per line because the stock is from a few different places.
For example, one stock is from the back street and another stock is from the other block.
If I use the total discount for the sales order, it doubles the same order if the inventory comes from different places.
and if I use the calculation to make the discount per line, it will bring line by line (for sure).
Was there any other possibility?
I tried with variable, but I can not pass more than one value on the same variable.
SELECT
MONTH(X.DOCDATE) MES,
YEAR(X.DOCDATE) ANO,
(100 - X.DiscPrcnt)* SUM(LineTotal) /100 as 'TOTAL'
FROM RDR1 INNER JOIN ORDR X ON RDR1.DocEntry = X.DocEntry
WHERE X.CANCELED <> 'Y'
AND X.DocTotal > 0
AND X.DocDate BETWEEN '20140101' AND '20190630'
AND OcrCode IN ('EXT', 'EXT-JD')
Group by
X.DOCDATE,
X.DiscPrcnt
ORDER BY X.DOCDATE
I would like it to be:
Month YEAR Total
1 2014 5000
2 2014 7000
I imagine you want to be grouping by month and year rather than the full date. Also, I think you may not want a separate row for each discount percent value right?
How about this query?:-
SELECT
MONTH(X.DOCDATE) MES,
YEAR(X.DOCDATE) ANO,
SUM((100 - X.DiscPrcnt)* X.LineTotal/100) as 'TOTAL'
FROM RDR1 INNER JOIN ORDR X ON RDR1.DocEntry = X.DocEntry
WHERE X.CANCELED <> 'Y'
AND X.DocTotal > 0
AND X.DocDate BETWEEN '20140101' AND '20190630'
AND OcrCode IN ('EXT', 'EXT-JD')
Group by
YEAR(X.DOCDATE),
MONTH(X.DOCDATE)
ORDER BY
YEAR(X.DOCDATE),
MONTH(X.DOCDATE)

SQL Server - logic to allow me to do a calculation in the where statement

I have searched for an answer for ages with no luck for my particular problem.
I have been asked to create a script to extract data for a mail-merge. Our billing team need to identify users who we have sent final warning notices to but have still not paid their bills.
The biggest challenge that I have been unable to overcome is that some of the customers may have done one of the following:
not made any payments for the outstanding amount
paid the outstanding amount in full in one payment
paid the outstanding amount in full with multiple payments
paid part of the outstanding amount in one or multiple payments
The data that was used to generate the final warning notices is in a table with the outstanding amount appearing as a positive number, and any payments that have been made are in a different table as a negative number.
In my query identifying customers from scenario 1 and 2 would be fairly easy to identify, but 3 and 4 are causing me headaches. I had the idea of adding the outstanding amount to a sum of any payments made. If the sum total is > 0 then the customer has not paid enough to cover the outstanding amount. I have developed a sub-query to get a total of all payments made after a certain date but I can't get the query to add that to the outstanding amount and then check to see if the balance is greater than 0. Error I get is "Cannot perform an aggregate function on an expression containing an aggregate or a subquery."
Can someone recommend a different approach to this query?
SELECT
finalwarning.table_no AS [Property No],
finalwarning.value_1 AS [Arrears Balance],
finalwarning.date_1 AS [Notice Date]
FROM
finalwarning
WHERE
finalwarning.table_no = 172030
AND finalwarning.ref_3 = 'Final'
AND ((SELECT
CASE
WHEN EXISTS (SELECT 1
FROM paymentsmade
WHERE PROPERTY_NO = 1234
AND TRANSACTION_DESC = 'Receipt'
AND TRANSACTION_DATE > '2017-05-01 00:00:00.000'
GROUP BY TRANSACTION_DESC)
THEN (SELECT SUM(amount)
FROM paymentsmade
WHERE paymentsmade.PROPERTY_NO = 1234
AND paymentsmade.TRANSACTION_DESC = 'Receipt'
AND paymentsmade.TRANSACTION_DATE > '2017-05-01 00:00:00.000'
GROUP BY paymentsmade.TRANSACTION_DESC)
ELSE '0'
END) + finalwarning.value_1) < 0
CTE are our friends and really help get the hard work done for us and allow for easier writing of the core SQL. The example below takes your structure and applies the concept of a payments CTE which will aggregate payments by property no and provide for all of the calculations you need to perform in your evaluation. I was uncertain about how the date came into play and the join might be wrong because there were 2 different numbers provided for property_no in the example but I assumed they were one and the same.
WITH paymentCTE (property_no, amount, transaction_desc, cntpayments)
as
(select property_no, sum(amount) as amount, transaction_desc, count(*)
from paymentsmade
where TRANSACTION_DATE > > '2017-05-01 00:00:00.000'
group by property_no, transaction_desc
)
SELECT fw.table_no AS [Property No]
, fw.value_1 AS [Arrears Balance]
, fw.date_1 AS [Notice Date]
, coalesce(p1.amount,0) as [Payments Made]
, fw.value_1+coalesce(p1.amount,0) as [Outstanding Balance]
, coalesce(p1.cntpayments, 0) as [Number of Payments]
FROM finalwarning fw
left outer join paymentCTE p1
on fw.table_no = p1.property_no
and p1.Transaction_desc = 'Receipt'
WHERE p1.cntpayments is null
or (coalesce(p1.cntpayments, 0) = 1 and fw.value_1 + coalesce(p1.amount,0) = 0)
or (coalesce(p1.cntpayments, 0) > 1 and fw.value_1 + coalesce(p1.amount,0) = 0)
or (coalesce(p1.cntpayments, 0) > 0 and fw.value_1 + coalesce(p1.amount,0)<> 0)

simple sql query highest sales

There are 2 tables - Products and Sales
Products
prod_id
prod_nm
Sales
prod_id
cust_id
sls_dt
sls_amt
Write a query selecting ALL the products. For each product show total of sales amounts in the past 30 days or 0 if not sold in 30 day withoug using subqueries.
Since different RDBMS have different date functions, you can filter by date using the following pseudo code - sls_dt > now() - 30.
Im new to sql and im trying it like this as i found this online.
Select prod_id, prod_nm from(
Select sls_amt
From Sales) as t
Where t.rank = 1
However, this isnt' working. Any help is appreciated
Try below:
select p.prod_id,
p.prod_nm,
sum(s.sls_amt)
from products p
left outer join Sales s on p.prod_id = s.prod_id
and s.sls_dt > now() - 30
group by p.prod_id,
p.prod_nm;

Revenue year by year SQL Server query

I have the following query which provides me with the item and item details, values, rate and quantity across each location.
I am trying to get the yearly revenue based on the Start and End Date. Example, if the chosen date was 2013-2015. The final result will create 3 columns one for 2013 revenue, one for 2014 revenue and one for 2015 revenue.
I am a newbie and still not an expert in writing queries, but here is what I have currently:
SELECT
department,
item,
itemdesc,
qty1,
qty2,
rate_1,
rate_2,
SUM(mm.days*mm.rate*mm.qty)
FROM
items it
LEFT JOIN
(SELECT
i.days, i.rate, i.days, ii.todate, ii.itemid
FROM
invoiceofitems ii
JOIN
invoices i on i.id = ii.id
WHERE
ii.todate BETWEEN #StartDate and #EndDate) mm ON mm.itemid = it.itemid
GROUP BY
department,
item,
itemdesc,
qty1, qty2,
rate_1, rate_2
ORDER BY
item
However, this does not provide me with a year to year aggregation of invoice revenue that I require.
I know this is possible to achieve via iterating through this. But how would I accomplish this and where would I start on this?
Would I need to know the start and end date of each year and iterate through that and then add a counter to the year until year= EndDate?
I'm extremely confused. Help would be appreciated.
I hope that PIVOT and YEAR help you to solve this problem (some columns are omitted):
;WITH SRC(department,item, ... , rate_2, yr, calculation) AS
(SELECT it.department, it.item, ..., it.rate_2, YEAR(ii.todate) as yr,
(i.days * i.rate *i.qty) as calculation
FROM items it
LEFT JOIN invoiceofitems ii ON ii.itemid = it.itemid
JOIN invoices i ON i.id = ii.id)
SELECT department,item, ..., [2013],[2014],[2015]
FROM SRC
PIVOT
(SUM(calculation) FOR yr IN ([2013],[2014],[2015])) PVT
The YEAR function returns only 'year' part of your date and makes grouping easier. PIVOT just rotates grouped data from rows to columns.