Need all Sales Reps on one Line - sql

Below I have the following SQL Statement:
WITH SalesDetail as (
SELECT
PostAR.TxDate
,PostAR.AccountLink
,PostST.AccountLink AS StkLnk
,PostST.Quantity AS QtySold
,PostST.cAuditNumber
,(PostST.Credit-PostST.Debit)-(PostST.Quantity*PostST.Cost) AS Profit
,(((PostST.Credit-PostST.Debit)-(PostST.Quantity*PostST.Cost)))/((((PostST.Credit-PostST.Debit))))*100 AS GrossProfitPercent
,(PostST.Quantity*PostST.Cost) AS Cost
,(PostST.Credit-PostST.Debit) AS TotSales
,(((PostST.Credit-PostST.Debit)-(PostST.Quantity*PostST.Cost))) / ((((PostST.Quantity*PostST.Cost)+(0.00000000000001))))*100 AS MarkUpPercent
,concat(StkItem.Code, ' - ' ,StkItem.Description_1) AS StkItemCode
,SalesRep.Code AS RepCode
,SalesRep.Name AS RepName
,Client.Account CustID
,Client.Name AS CustName
,CASE
WHEN ((((PostST.Credit+PostST.Debit)-(PostST.Cost*PostST.Quantity))/((PostST.Cost+0.0000001)*PostST.Quantity))*100) > 0 AND ((((PostST.Credit+PostST.Debit)-((PostST.Cost+0.0000001)*PostST.Quantity))/((PostST.Cost+0.0000001)*PostST.Quantity))*100) < 25 THEN 2
WHEN ((((PostST.Credit+PostST.Debit)-(PostST.Cost*PostST.Quantity))/((PostST.Cost+0.0000001)*PostST.Quantity))*100) >= 25 AND ((((PostST.Credit+PostST.Debit)-((PostST.Cost+0.0000001)*PostST.Quantity))/((PostST.Cost+0.0000001)*PostST.Quantity))*100) < 35 THEN 2.5
WHEN ((((PostST.Credit+PostST.Debit)-(PostST.Cost*PostST.Quantity))/((PostST.Cost+0.0000001)*PostST.Quantity))*100) >= 35 AND ((((PostST.Credit+PostST.Debit)-((PostST.Cost+0.0000001)*PostST.Quantity))/((PostST.Cost+0.0000001)*PostST.Quantity))*100) < 45 THEN 3
WHEN ((((PostST.Credit+PostST.Debit)-(PostST.Cost*PostST.Quantity))/((PostST.Cost+0.0000001)*PostST.Quantity))*100) >= 45 AND ((((PostST.Credit+PostST.Debit)-((PostST.Cost+0.0000001)*PostST.Quantity))/((PostST.Cost+0.0000001)*PostST.Quantity))*100) < 55 THEN 3.5
WHEN ((((PostST.Credit+PostST.Debit)-(PostST.Cost*PostST.Quantity))/((PostST.Cost+0.0000001)*PostST.Quantity))*100) >= 55 THEN 4
ELSE 0
END AS CommPayablePercent
FROM PostAR
INNER JOIN PostST
ON PostST.cAuditNumber = PostAR.cAuditNumber
INNER JOIN StkItem
ON StkItem.StockLink = PostST.AccountLink
INNER JOIN SalesRep
ON SalesRep.idSalesRep = PostAR.RepID
INNER JOIN Client
ON Client.DCLink = PostAR.AccountLink
)
SELECT SalesDetail.RepName
, (((SalesDetail.CommPayablePercent)/100)) * ((SalesDetail.TotSales)) As RepTotComm
, SUM(SalesDetail.TotSales) AS TotalSales
FROM SalesDetail
GROUP BY SalesDetail.RepName, SalesDetail.TotSales, SalesDetail.CommPayablePercent
ORDER BY SalesDetail.RepName
I then get the following result:
As you can see, it is multipling the TotSales by my already determained CASE formulala. That is fine. However, I do not want the reps all on a each line. I want just the rep name and then the total commission payable.
Eg:
GRAY MEIRING - $5000 - $6000
and not:
GRAY MEIRING
GRAY MEIRING
GRAY MEIRING etc etc...
Is the issue coming from my SUM function or perhaps my GROUP BY function?
Many thanks! :)

You should use GROUP BY SalesDetail.RepName only, to achieve It, you can add subquery, try something like that:
................
SELECT RepName,
SUM(RepTotComm),
SUM(TotalSales)
FROM (
SELECT SalesDetail.RepName
, (((SalesDetail.CommPayablePercent)/100)) * ((SalesDetail.TotSales)) As RepTotComm
, SUM(SalesDetail.TotSales) AS TotalSales
FROM SalesDetail
GROUP BY SalesDetail.RepName, SalesDetail.TotSales, SalesDetail.CommPayablePercent
) x
GROUP BY RepName
ORDER BY RepName

Related

Bring through a newly created calculated column in another query

I have 2 separate queries below which run correctly.Now I've created a calculated column to provide a count of working days by YMs and would like to bring this through to query1(the join would be query1.Period = query2.Yms)
please see the query and outputs below.
SELECT Client, ClientGroup, Type, Value, Period, PeriodName, PeriodNumber, ClientName
FROM metrics.dbo.vw_KPI_001_Invoice
select YMs,sum(case when IsWorkDay = 'X' then 1 else 0 end) from IESAONLINE.Dbo.DS_Dates
where Year > '2013'
group by YMs
Query 1
Client ClientGroup Type Value Period PeriodName PeriodNumber ClientName
0LG0 KarroFoods Stock 5691.68 201506 Week 06 2015 35 Karro Foods Scunthorpe
Query 2
YMs (No column name)
201401 23
Would the following work:
SELECT Client, ClientGroup, Type, Value, Period, PeriodName, PeriodNumber, ClientName, cnt
FROM metrics.dbo.vw_KPI_001_Invoice q1
INNER JOIN (select YMs,sum(case when IsWorkDay = 'X' then 1 else 0 end) as cnt from IESAONLINE.Dbo.DS_Dates
where Year > '2013'
group by YMs ) q2 ON q1.Period = q2.YMs
If a value isn't always available then you might consider changing the INNER JOIN to an OUTER JOIN.

SQL Server query with multiple select

I have a query which select all car makes and count each make quantity in response
SELECT
q.Make, Count(q.ID)
FROM
(SELECT
cars.ID, cars.Make, cars.Model,
cars.Year1, cars.Month1, cars.KM, cars.VIN,
cars.Fuel, cars.EngineCap, cars.PowerKW,
cars.GearBox, cars.BodyType, cars.BodyColor,
cars.Doors, cars.FullName, Transport.address,
(DateDiff(second,Getdate(),cars.AuEnd)) as r,
cars.AuEnd, cars.BuyNowPrice, cars.CurrentPrice
FROM
cars
LEFT JOIN
Transport ON Cars.TransportFrom = Transport.ID
WHERE
Active = 'True'
AND AuEnd > GETDATE()
AND year1 >= 1900 AND year1 <= 2015
AND Make in ('AUDi', 'AIXAM', 'ALPINA')
ORDER BY
cars.make ASC, cars.model ASC
OFFSET 50 ROWS FETCH NEXT 50 ROWS ONLY) AS q
GROUP BY
q.make ORDER BY q.make ASC;
Now I need get in result as third field each make total count without offset,
so now I get result
Make CountInResponse
AIXAM 1
ALPINA 1
AUDI 48
But I need to get
Make CountInResponse Total
AIXAM 1 1
ALPINA 1 1
AUDI 48 100
I think I need something like
SELECT
q.Make, Count(q.ID),
(SELECT Make, Count(ID)
FROM cars
WHERE Active = 'True' AND AuEnd > GETDATE()
AND year1 >= 1900 AND year1 <= 2015
AND Make in ('AUDI', 'AIXAM', 'ALPINA')
GROUP BY Make) as q2
FROM
(SELECT
cars.ID, cars.Make, cars.Model,
cars.Year1, cars.Month1, cars.KM, cars.VIN,
cars.Fuel, cars.EngineCap, cars.PowerKW,
cars.GearBox, cars.BodyType, cars.BodyColor,
cars.Doors, cars.FullName, Transport.address,
(DateDiff(second,Getdate(),cars.AuEnd)) as r,
cars.AuEnd, cars.BuyNowPrice, cars.CurrentPrice
FROM
cars
LEFT JOIN
Transport ON Cars.TransportFrom = Transport.ID
WHERE
Active = 'True'
AND AuEnd > GETDATE()
AND year1 >= 1900 AND year1 <= 2015
AND Make in ('AUDi', 'AIXAM', 'ALPINA')
ORDER BY
cars.make ASC, cars.model ASC
OFFSET 50 ROWS FETCH NEXT 50 ROWS ONLY) AS q
But I get an error
Msg 116, Level 16, State 1, Line 10
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
How to write right syntax?
The problem is you are selecting two columns in q2 (ie) Make, Count(ID) you cannot do that in SQL Server.
Try something like this.
WITH cte AS
(
SELECT
row_number() OVER(order by cars.make ASC,cars.model ASC) AS rn,
cars.id, cars.make
FROM
cars
LEFT JOIN
transport ON cars.transportfrom = transport.id
WHERE
active = 'True'
AND auend > getdate()
AND year1 >= 1900 AND year1 <= 2015
AND make IN ('AUDI', 'AIXAM', 'ALPINA')
)
SELECT
make ,
count(CASE WHEN RN BETWEEN 50 AND 100 THEN 1 END) AS countinresponse,
count(1) AS total
FROM
cte
GROUP BY
make
Or you need to convert the sub-query in select to correlated sub-query
SELECT q.make,
Count(q.id) countinresponse,
(
SELECT Count(id)
FROM cars C1
WHERE c1.id = q.id
AND active='True'
AND auend > Getdate()
AND year1 >= 1900
AND year1 <= 2015
AND make IN ('AUDi',
'AIXAM',
'ALPINA')
GROUP BY make) AS total
FROM (
SELECT cars.id,
cars.make
FROM cars
LEFT JOIN transport
ON cars.transportfrom=transport.id
WHERE active='True'
AND auend > Getdate()
AND year1 >= 1900
AND year1 <= 2015
AND make IN ('AUDi',
'AIXAM',
'ALPINA')
ORDER BY cars.make ASC,
cars.model ASC offset 50 rowsfetch next 50 rows only ) AS q
GROUP BY q.make
ORDER BY q.make ASC;

Need Help on SQL

I actually found something that I could work on regarding my problem "Need help with sql query". But I would appreciate it if I can get an answer to my specific question.
I have 2 tables one is TRANSACTIONS and one is EXPENSES.
TRANSACTION:
transaction_id
emp_id
sales_date
total_sales
And
EXPENSES:
expenses_id
emp_id
expense_date
expenses1
expenses2
total_expenses
I would like to sum all the TRANSACTION.transaction_amount AS sales_sum WHERE TRANSACTION.sales_date = #sales_date and TRANSACTION.emp_id = #emp_id ..... and then, subtract the EXPENSES.total_expenses as expenses_deducted_sales WHERE EXPENSES.emp_id = TRANSACTION.emp_id AND TRANSACTION.sales_date = EXPENSES.expense_date
PLEASE HELP.. Thank you
Ex
transaction_id emp_id sales_date total_sales
1 101 11/11/2012 300
2 101 11/11/2012 400
3 101 11/11/2012 300
expenses_id emp_id expenses_date expenses1 expenses2 total_expenses
1 101 11/11/2012 100 100 200
2 102 12/12/2012 50 50 100
3 103 10/12/2012 200 200 400
expenses_deducted_sales = (300 + 400 + 300) - 200
I've tried the code given by AHiggins and came up with these:
SELECT
CashTransactionsTbl.emp_id,
CashTransactionsTbl.trans_date,
CashTransactionsTbl.total_amt - ISNULL(ExpensesTbl.total_expenses,0) AS expenses_deducted_sales
FROM
(
SELECT
emp_id,
trans_date,
SUM(total_amt) AS sales_sum
FROM CashTransactionsTbl
GROUP BY emp_id, trans_date
) tr
LEFT JOIN
ExpensesTbl ON
tr.emp_id = ExpensesTbl.emp_id AND
tr.trans_date = ExpensesTbl.trans_date
WHERE
tr.trans_date = 2014-07-10
but no I have this error that says:
"Operand type clash: date is incompatible with int"
Please help!
You need two derived tables: One with the transaction sum per employee, one with the expenses sum per employee. Full outer join These to get all records.
select
coalesce(t.emp_id, e.emp_id) as emp_id,
coalesce(t.sum_sales, 0) as sum_sales,
coalesce(e.sum_expenses, 0) as sum_expenses,
coalesce(t.sum_sales, 0) - coalesce(e.sum_expenses, 0) as expenses_deducted_sales
from
(
select emp_id, sum(total_sales) as sum_sales
from transaction
group by emp_id
) t
full outer join
(
select emp_id, sum(total_expenses) as sum_expenses
from expense
group by emp_id
) e on e.emp_id = t.emp_id;
You need to get the aggregate data from Transactions before you match that with the data from Expenses, like so:
SELECT
tr.Emp_ID,
tr.Sales_Date,
tr.Sales_Sum - ISNULL(Expenses.Total_Expenses,0) AS Expenses_Deducted_Sales
FROM
(
SELECT
Emp_ID,
Sales_Date,
SUM(Total_Sales) Sales_Sum
FROM Transactions
) tr
LEFT JOIN
Expenses ON
tr.Emp_ID = Expenses.Emp_ID AND
tr.Sales_Date = Expenses.Expenses_Date
WHERE
tr.Sales_Date = #sales_date -- this could also go under the 'FROM Transactions' statement
This is pretty rough but something like this would work:
Select T_Sales.*,T_Sales.totalsales-totalexpesnses 'Expenses_deducted_sales'
from (
select t.emp_id,sales_date,SUM(totalsales) 'totalsales'
from #transaction t
group by t.emp_id,sales_date
) T_Sales
left join #expenses e
on T_Sales.emp_id = e.emp_id
and T_Sales.sales_date = e.expenses_date
where sales_date = #sales_date
ps. Apologies for spelling - quick work.

Calculate the qty of items that were purchased more than once by a customer - but need to exclude the first order qty

SELECT TOP 100 PERCENT soheader.custid,SOHeader.OrdNbr, SOLine.InvtID, SOLine.Descr,SOLine.QtyOrd
FROM SOHeader INNER JOIN
SOLine ON SOHeader.OrdNbr = SOLine.OrdNbr
WHERE (SOHeader.OrdDate >= CONVERT(DATETIME, '2013-06-01 00:00:00', 102)) AND (SOHeader.OrdDate <= GETDATE()) AND (SOHeader.CustID = '69065')
ORDER BY SOLine.InvtID, SOHeader.OrdNbr
here is my sample data
69065 WO0175279 69407 Jazzy Laces White 3
69065 WO0175393 69407 Jazzy Laces White 6
69065 WO0175393 69407 Jazzy Laces White 9
Now I want to know how to get the total qty of this item ordered after the first order. I do not want to include the qty of 3 in the first record above. I just want to include the qty of 6 in the first reorder and the qty 9 of the second reorder which equals the qty of 15.
69065 is the customer ID
WO##### is the order ID
69407 is the inventory ID
SELECT invtId, SUM(QtyOrd)
FROM (
SELECT invtId,
qtyOrd,
ROW_NUMBER() OVER (PARTITION BY invtId ORDER BY h.ordDate, h.ordNbr) rn
FROM soLine l
JOIN soHeader h
ON h.ordNbr = l.ordNbr
WHERE l.custId = 69065
) q
WHERE rn > 1
GROUP BY
invtId
WITH cl
as
(select *, ROW_NUMBER() OVER (PARTITION BY InvtID ORDER BY QtyOrd) rn
from t)
select InvtID, QtyOrd,
(select SUM(QtyOrd) from cl oo
where o.InvtID = oo.InvtID and o.rn -1 > 0
and rn between o.rn -1 and o.rn) as 'sm'
from cl o
Here's a Demo on SqlFiddle.

SQL Query in CRM Report

A "Case" in CRM has a field called "Status" with four options.
I'm trying to
build a report in CRM that fills a table with every week of the year (each row is a different week), and then counts the number of cases that have each Status option (the columns would be each of the Status options).
The table would look like this
Status 1 Status 2 Status 3
Week 1 3 55 4
Week 2 5 23 5
Week 3 14 11 33
So far I have the following:
SELECT
SUM(case WHEN status = 1 then 1 else 0 end) Status1,
SUM(case WHEN status = 2 then 1 else 0 end) Status2,
SUM(case WHEN status = 3 then 1 else 0 end) Status3,
SUM(case WHEN status = 4 then 1 else 0 end) Status4,
SUM(case WHEN status = 5 then 1 else 0 end) Status5
FROM [DB].[dbo].[Contact]
Which gives me the following:
Status 1 Status 2 Status 3
2 43 53
Now I need to somehow split this into 52 rows for the past year and filter these results by date (columns in the Contact table). I'm a bit new to SQL queries and CRM - any help here would be much appreciated.
Here is a SQLFiddle with my progress and sample data: http://sqlfiddle.com/#!2/85b19/1
Sounds like you want to group by a range. The trick is to create a new field that represents each range (for you one per year) and group by that.
Since it also seems like you want an infinite range of dates, marc_s has a good summary for how to do the group by trick with dates in a generic way: SQL group by frequency within a date range
So, let's break this down:
You want to make a report that shows, for each contact, a breakdown, week by week, of the number of cases registered to that contact, which is divided into three columns, one for each StateCode.
If this is the case, then you would need to have 52 date records (or so) for each contact. For calendar like requests, it's always good to have a separate calendar table that lets you query from it. Dan Guzman has a blog entry that creates a useful calendar table which I'll use in the query.
WITH WeekNumbers AS
(
SELECT
FirstDateOfWeek,
-- order by first date of week, grouping calendar year to produce week numbers
WeekNumber = row_number() OVER (PARTITION BY CalendarYear ORDER BY FirstDateOfWeek)
FROM
master.dbo.Calendar -- created from script
GROUP BY
FirstDateOfWeek,
CalendarYear
), Calendar AS
(
SELECT
WeekNumber =
(
SELECT
WeekNumber
FROM
WeekNumbers WN
WHERE
C.FirstDateOfWeek = WN.FirstDateOfWeek
),
*
FROM
master.dbo.Calendar C
WHERE
CalendarDate BETWEEN '1/1/2012' AND getutcdate()
)
SELECT
C.FullName,
----include the below if the data is necessary
--Cl.WeekNumber,
--Cl.CalendarYear,
--Cl.FirstDateOfWeek,
--Cl.LastDateOfWeek,
'Week: ' + CAST(Cl.WeekNumber AS VARCHAR(20))
+ ', Year: ' + CAST(Cl.CalendarYear AS VARCHAR(20)) WeekNumber
FROM
CRM.dbo.Contact C
-- use a cartesian join to produce a table list
CROSS JOIN
(
SELECT
DISTINCT WeekNumber,
CalendarYear,
FirstDateOfWeek,
LastDateOfWeek
FROM
Calendar
) Cl
ORDER BY
C.FullName,
Cl.WeekNumber
This is different from the solution Ben linked to because Marc's query only returns weeks where there is a matching value, whereas you may or may not want to see even the weeks where there is no activity.
Once you have your core tables of contacts split out week by week as in the above (or altered for your specific time period), you can simply add a subquery for each StateCode to see the breakdown in columns as in the final query below.
WITH WeekNumbers AS
(
SELECT
FirstDateOfWeek,
WeekNumber = row_number() OVER (PARTITION BY CalendarYear ORDER BY FirstDateOfWeek)
FROM
master.dbo.Calendar
GROUP BY
FirstDateOfWeek,
CalendarYear
), Calendar AS
(
SELECT
WeekNumber =
(
SELECT
WeekNumber
FROM
WeekNumbers WN
WHERE
C.FirstDateOfWeek = WN.FirstDateOfWeek
),
*
FROM
master.dbo.Calendar C
WHERE
CalendarDate BETWEEN '1/1/2012' AND getutcdate()
)
SELECT
C.FullName,
--Cl.WeekNumber,
--Cl.CalendarYear,
--Cl.FirstDateOfWeek,
--Cl.LastDateOfWeek,
'Week: ' + CAST(Cl.WeekNumber AS VARCHAR(20)) +', Year: ' + CAST(Cl.CalendarYear AS VARCHAR(20)) WeekNumber,
(
SELECT
count(*)
FROM
CRM.dbo.Incident I
INNER JOIN CRM.dbo.StringMap SM ON
I.StateCode = SM.AttributeValue
INNER JOIN
(
SELECT
DISTINCT ME.Name,
ME.ObjectTypeCode
FROM
CRM.MetadataSchema.Entity ME
) E ON
SM.ObjectTypeCode = E.ObjectTypeCode
WHERE
I.ModifiedOn >= Cl.FirstDateOfWeek
AND I.ModifiedOn < dateadd(day, 1, Cl.LastDateOfWeek)
AND E.Name = 'incident'
AND SM.AttributeName = 'statecode'
AND SM.LangId = 1033
AND I.CustomerId = C.ContactId
AND SM.Value = 'Active'
) ActiveCases,
(
SELECT
count(*)
FROM
CRM.dbo.Incident I
INNER JOIN CRM.dbo.StringMap SM ON
I.StateCode = SM.AttributeValue
INNER JOIN
(
SELECT
DISTINCT ME.Name,
ME.ObjectTypeCode
FROM
CRM.MetadataSchema.Entity ME
) E ON
SM.ObjectTypeCode = E.ObjectTypeCode
WHERE
I.ModifiedOn >= Cl.FirstDateOfWeek
AND I.ModifiedOn < dateadd(day, 1, Cl.LastDateOfWeek)
AND E.Name = 'incident'
AND SM.AttributeName = 'statecode'
AND SM.LangId = 1033
AND I.CustomerId = C.ContactId
AND SM.Value = 'Resolved'
) ResolvedCases,
(
SELECT
count(*)
FROM
CRM.dbo.Incident I
INNER JOIN CRM.dbo.StringMap SM ON
I.StateCode = SM.AttributeValue
INNER JOIN
(
SELECT
DISTINCT ME.Name,
ME.ObjectTypeCode
FROM
CRM.MetadataSchema.Entity ME
) E ON
SM.ObjectTypeCode = E.ObjectTypeCode
WHERE
I.ModifiedOn >= Cl.FirstDateOfWeek
AND I.ModifiedOn < dateadd(day, 1, Cl.LastDateOfWeek)
AND E.Name = 'incident'
AND SM.AttributeName = 'statecode'
AND SM.LangId = 1033
AND I.CustomerId = C.ContactId
AND SM.Value = 'Canceled'
) CancelledCases
FROM
CRM.dbo.Contact C
CROSS JOIN
(
SELECT
DISTINCT WeekNumber,
CalendarYear,
FirstDateOfWeek,
LastDateOfWeek
FROM
Calendar
) Cl
ORDER BY
C.FullName,
Cl.WeekNumber