I work with the AventureWorks2014 database in Microsoft SQL Server. I need to create a view that will show the CustomerID, the full name and the TOTAL amount sold to client through the web.
My problem is that I can't seem to get the values corresponding to a single customer add up so that a single customer answers to a single line in my result. This is the code I have, any help would be appreciated. I basically need to show the total amount sold to clients on the web.
if object_id('vTotalWebSalesPerCustomer', 'v') is not null
drop view vTotalWebSalesPerCustomer;
go
create view vTotalWebSalesPerCustomer
as
select distinct
c.CustomerID,
ltrim(rtrim(concat(concat(concat(concat(concat(concat(concat(p.Title, ' '), p.LastName), ', '), ' '), p.FirstName), ' '), p.Suffix))) as NomClient,
soh.TotalDue
from
[Sales].[Customer] as c
left join
[Person].[Person] as p on c.CustomerID = p.BusinessEntityID
left join
[Sales].[SalesOrderHeader] as soh on soh.CustomerID = c.CustomerID
where
year(soh.OrderDate) = 2014
and datepart(quarter, soh.OrderDate) = 1
and [OnlineOrderFlag] = 1
go
select *
from vTotalWebSalesPerCustomer
Thanks
Sounds like you need to use GROUP BY and SUM(), example:
SELECT column-names
FROM table-name
WHERE condition
GROUP BY column-names
ORDER BY column-names
Such as:
SELECT SUM(O.TotalPrice), C.FirstName, C.LastName
FROM [Order] O JOIN Customer C
ON O.CustomerId = C.Id
GROUP BY C.FirstName, C.LastName
ORDER BY SUM(O.TotalPrice) DESC
Would return:
Sum FirstName LastName
117483.39 Horst Kloss
115673.39 Jose Pavarotti
113236.68 Roland Mendel
57317.39 Patricia McKenna
52245.90 Paula Wilson
34101.15 Mario Pontes
32555.55 Maria Larsson
DISTINCT filters result rows to remove duplicates. What I think you want is to aggregate rows. Perhaps this will do what you want:
create view vTotalWebSalesPerCustomer as
select c.CustomerID,
ltrim(rtrim(concat(concat(concat(concat(concat(concat(concat(p.Title, ' '), p.LastName), ', '), ' '), p.FirstName), ' '), p.Suffix))) as NomClient,
sum(soh.TotalDue) as TotalDue
from [Sales].[Customer] as c
left join [Person].[Person] as p on c.CustomerID = p.BusinessEntityID
left join [Sales].[SalesOrderHeader] as soh on soh.CustomerID = c.CustomerID
where year(soh.OrderDate) = 2014 and datepart(quarter, soh.OrderDate)=1 and [OnlineOrderFlag] = 1
group by c.CustomerID,NomClient
Note that I removed distinct, added sum operator on the amount you want to total, and group by the customer id and name fields (SQL Server requires that you list in the GROUP BY all result columns which are not being aggregated).
You can use the following VIEW using a GROUP BY on the SELECT:
IF OBJECT_ID('vTotalWebSalesPerCustomer', 'v') IS NOT NULL
DROP VIEW vTotalWebSalesPerCustomer;
GO
CREATE VIEW vTotalWebSalesPerCustomer AS
SELECT
x.CustomerID,
LTRIM(RTRIM(CONCAT(p.Title, ' ', p.LastName, ', ', p.FirstName, ' ', p.Suffix))) AS NomClient,
x.TotalDue
FROM (
SELECT
c.CustomerID AS CustomerID,
SUM(soh.TotalDue) AS TotalDue
FROM [Sales].[Customer] AS c
LEFT JOIN [Sales].[SalesOrderHeader] AS soh ON soh.CustomerID = c.CustomerID
WHERE YEAR(soh.OrderDate) = 2014 AND DATEPART(quarter, soh.OrderDate) = 1 AND [OnlineOrderFlag] = 1
GROUP BY c.CustomerID
)x LEFT JOIN [Person].[Person] AS p ON x.CustomerID = p.BusinessEntityID
GO
Note: You only need one CONCAT function to concat all string values.
Related
I have one customer table and one address table.For each customer there should be multiple address in address Table
I need A stored procedure to select a customer details and his address on top from address table
parameter to select customer is companyID
SELECT top 1 s.Addr1 as ShipAddress_Addr1,s.Addr2 as ShipAddress_Addr2,s.Addr3 as ShipAddress_Addr3,
s.Addr4 as ShipAddress_Addr4,s.Addr5 as ShipAddress_Addr5,
s.City as ShipAddress_City,s.[state] as ShipAddress_State,s.PostalCode as ShipAddress_PostalCode,
s.Country as ShipAddress_Country,s.Note as ShipAddress_Note ,c.CustomerID,c.[TimeCreated], c.[FullName],c.FirstName,c.LastName,c.Phone, c.Email,
c.BillAddress_Addr1, c.[BillAddress_Addr2],c. [BillAddress_Addr3],c. [BillAddress_Addr4],c.[BillAddress_Addr5],
c.BillAddress_City,c.BillAddress_State,c.BillAddress_PostalCode,c.BillAddress_Country,c.BillAddress_Note
FROM Customer c left join [dbo].[CustomerShipToAddress] s on s.customerListID=c.CustomerID
WHERE c.IsActive = 1 and c.CompanyID = #CompanyID
You can outer apply the latest address for each customer like this:
select c.customerid, c.name, c.accno, c.txnid, ta.add1, ta.add2
from customertable c
outer apply (select top 1 a.add1, a.add2 from addresstable a where a.customerid = c.customerid order by a.addressid desc) ta
The sub-query in the outer apply with always return 0 or 1 rows for each customer, so it will not cause duplication of rows when you join it with customertable.
SELECT TOP 1, c.customerid, c.name, a.add1 FROM customertable c, addresstable a WHERE c.customerid == a.customerid
this will return the first row basically. this is what you are asking for, but not what you mean i assume.
if you want to look this up for a specific customer use
SELECT TOP 1, c.customerid, c.name, a.add1 FROM customertable c, addresstable a WHERE c.customerid == a.customerid AND c.customerid == "yourcustomerid"
or even
SELECT c.customerid, c.name, DISTINCT a.add1 FROM customertable c, addresstable a WHERE c.customerid == a.customerid
I have the records below. I want to show subjects when Monday in column all subjects appear on Monday with start time and end time. How do I do this?
SELECT t.teacher_name, tci.class_name, tsb.Subject_Name, tdn.DaysName,
tss.subject_start, tss.subject_end
FROM tblsubjectSchedule tss
INNER JOIN tblsubjects tsb ON tss.subject_id = tsb.Idx
INNER JOIN tblclassinfo tci ON tss.class_id = tci.Idx
INNER JOIN tbldaysnames tdn ON tss.days_id = tdn.Idx
INNER JOIN tblteacher t ON tss.techer_id = t.Idx
WHERE tss.class_id = 2 AND t.school_id = 1
Your attachment is not completely clear. Are you going to ignore teacher_name on result?
In your screenshot you haven't included 'samad teacheer' on Monday results. You want the query only for Monday date?
If you only focus on class and days and date, I got below. please refer the attachment.Let me know if it works for you and accept my answer.
SELECT t1.class_name,t1.daysname,
subject_name =REPLACE( (SELECT (subject_name+'-start:'+CONVERT(VARCHAR, subject_start, 120)+'-End:'+CONVERT(VARCHAR, subject_end, 120)) AS [data()]
FROM [practice].[dbo].[test] t2
WHERE t2.daysname = t1.daysname
ORDER BY subject_name
FOR XML PATH('')
), ' ', ';')
FROM [practice].[dbo].[test] t1
GROUP BY daysname,class_name ;
You could also add teacher name to the schedule column: see the attachment
SELECT t1.class_name,t1.daysname,
schedule =REPLACE( (SELECT (teacher_name+'-'+subject_name+'-start:'+CONVERT(VARCHAR, subject_start, 120)+'-End:'+CONVERT(VARCHAR, subject_end, 120)) AS [data()]
FROM [practice].[dbo].[test] t2
WHERE t2.daysname = t1.daysname
ORDER BY subject_name
FOR XML PATH('')
), ' ', ';')
FROM [practice].[dbo].[test] t1
GROUP BY daysname,class_name ;
Here is the query only for the 'Monday'
SELECT t1.class_name,t1.daysname,
schedule =REPLACE( (SELECT (teacher_name+'-'+subject_name+'-start:'+CONVERT(VARCHAR, subject_start, 120)+'-End:'+CONVERT(VARCHAR, subject_end, 120)) AS [data()]
FROM [practice].[dbo].[test] t2
WHERE t2.daysname = t1.daysname
ORDER BY subject_name
FOR XML PATH('')
), ' ', ';')
FROM [practice].[dbo].[test] t1 where daysname='Monday'
GROUP BY daysname,class_name ;
I am trying to get list of customers that have orders in January & February,but not in March
SELECT distinct C.CustID, FirstName + ', ' + LastName AS CustomerName, OrderDate
FROM Customers C JOIN Orders O ON
C.CustID = O.CustID
WHERE C.CustID in
(select CustID
from Customers
where month(OrderDate) >= 01)
and
C.CustID in
(select CustID
from Customers
where month(OrderDate) <= 02)
and
C.CustID IN
(select CustID
from Customers
where month(OrderDate) != 03);
Have a go with this:
SELECT C.CustID, C.FirstName + ', ' + C.LastName AS CustomerName, O1.OrderDate
FROM Customers C
INNER JOIN (
SELECT CustID FROM Orders WHERE month(OrderDate) IN (1,2)
) O1 ON C.CustID=O1.CustID
LEFT JOIN (
SELECT CustID FROM Orders WHERE month(OrderDate) IN (3)
) O2 ON C.CustID=O2.CustID
WHERE O2.CustID IS NULL
GROUP BY C.CustID, C.FirstName, C.LastName, O1.OrderDate
Find the customers that had orders in March and use a NOT IN operator instead of IN
SELECT distinct C.CustID, FirstName + ', ' + LastName AS CustomerName, OrderDate
FROM Customers C JOIN Orders O ON
C.CustID = O.CustID
WHERE C.CustID in
(select CustID
from ORders
where month(OrderDate) BETWEEN 1 AND 2)
AND C.CustID NOT IN
(select CustID
from ORders
where month(OrderDate) 03);
I also changed the first two where conditions into one so it's a smidge faster.
Also, as #Matthew pointed out, your CustID and OrderDate fields are probably on your Order table so it would work a bit better to use that in your subqueries.
SELECT C.CustID, C.FirstName + ', ' + C.LastName AS CustomerName, O1.OrderDate
FROM Customers C
LEFT OUTER JOIN
(SELECT CustID FROM Orders WHERE month(OrderDate) IN (3) ) O ON
O. CustID = C.CustID
WHERE month(C.OrderDate) IN (1,2)
AND O.CustID IS NULL
So basically I'm trying to replicate this query as a stored procedure.
Use ThisDB
SELECT FirstName + ' ' + LastName as FullName ,
sum(UnitPrice * Quantity) as 'Total Sales',
YEAR(OrderDate) as SalesYear
From Employees e
Join Orders o on o.EmployeeID = e.EmployeeID
join [Order Details] od on od.OrderID = o.OrderID
Group by LastName +' ' +FirstName, YEAR(OrderDate)
Order by 'Total Sales' desc
Edit: I noticed that the old query was gonna fail, but that don't change too much /edit
Unfortunately, I haven't found any good examples that help me translate what I know about queries to stored procedure syntax. Here is what i understand so far:
Use ThisDB;
go
CREATE PROCEDURE empSalesByYear as #Emp OUT
BEGIN
Set Emp = (SELECT Employees.FirstName, Employees.LastName ,
TotalSales = sum([Order Details].UnitPrice * [OrderDetails].Quantity),
YEAR(orders.OrderDate) as SalesYear
From Employees e
Join Orders o on o.EmployeeID = e.EmployeeID
join [Order Details] od on od.OrderID = o.OrderID
group by FirstName , LastName
Order by TotalSales desc)
END
GO
Predictably, SQL server give me the finger when I type all this in. . .
My goal here is a stored procedure that takes zero input parameters and outputs a table like the first query.
Thanks.
Further to my comment, you can just do:
CREATE PROCEDURE proc_GetEmpSalesByYear AS
SELECT FirstName + ' ' + LastName as FullName ,
sum(UnitPrice * Quantity) as 'Total Sales',
YEAR(OrderDate) as SalesYear
From ThisDB..Employees e
Join ThisDB..Orders o on o.EmployeeID = e.EmployeeID
join ThisDB..[Order Details] od on od.OrderID = o.OrderID
Group by LastName, FirstName Order by 'Total Sales' desc
GO
..unless you wanted to return a table output parameter?
(Removed the USE, missed that.. now using db..table format)
to the SSRS report server process that uses it? the name looks like a guid, but i need to find the reporting services reports that use it.
thanks very much
Here's a query I blogged about a while back that does the join:
;WITH cte (job_id, job_name, execution_time, execution_order)
AS
(
SELECT DISTINCT j.job_id
,j.name
,CONVERT(datetime, STUFF(STUFF(run_date,7,0,'/'),5,0,'/')
+ SPACE(1)
+ STUFF(STUFF(RIGHT('000000' + CONVERT(varchar(20), run_time), 6),5,0,':'),3,0,':'))
,ROW_NUMBER() OVER (PARTITION BY j.job_id ORDER BY CONVERT(datetime, STUFF(STUFF(run_date,7,0,'/'),5,0,'/')
+ SPACE(1)
+ STUFF(STUFF(RIGHT('000000' + CONVERT(varchar(20), run_time), 6),5,0,':'),3,0,':')) DESC)
FROM msdb.dbo.sysjobs j
INNER JOIN msdb.dbo.syscategories c ON j.category_id = c.category_id
LEFT OUTER JOIN msdb.dbo.sysjobhistory jh ON j.job_id = jh.job_id
WHERE c.name ='Report Server'
)
SELECT
x.job_name
,c.name
,x.execution_time
,c.path
,su.description
,CONVERT(varchar(max), su.ExtensionSettings) as ExtensionSettings
,'EXEC msdb..sp_start_job ''' + x.job_name + '''' as SQLStatement
FROM cte x
INNER JOIN dbo.Schedule sc ON x.job_name = CONVERT(varchar(100), sc.ScheduleID)
INNER JOIN dbo.ReportSchedule rs ON sc.ScheduleID = rs.ScheduleID
INNER JOIN dbo.Subscriptions su ON rs.SubscriptionID = su.SubscriptionID
INNER JOIN dbo.Catalog c ON su.Report_OID = c.ItemID
WHERE execution_order = 1
ORDER BY 3, 2
There doesn't appear to be a straightforward method to find this out.
The following query lists the subscription IDs and the reports to which they link
select s.SubscriptionID, c.Path
from ReportServer.dbo.Subscriptions as s
JOIN ReportServer.dbo.Catalog as c
on ItemID = Report_OID
The subscription ID is then referenced inside the job step, in the following format.
exec ReportServer.dbo.AddEvent #EventType='TimedSubscription', #EventData='~subscriptionID~'
It should be possible to write a query to join it all together, but I don't have time right now. I will try and update the question later.