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
Related
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.
i want to Write a query using the temporary date table to show rows for every customer for every month since the month they first purchased from us. The table should detail the customer ID, customer name, month, Date of first Purchase, Units Purchased that month, Value Purchased that month, Cumulative Units Purchased, Cumulative Value Purchased and the Days since last purchase and the last day of the month.
i've tried this code
select c.Id AS CustomerId
,c.FirstName+' '+c.LastName as CustomerName
,DATENAME(MM,d.OrderDate) AS MonthofFirstPurchase
--,sum(d.TotalAmount) AS CummulativeValue
,d.OrderDate AS DateOfFirstPurchase
,Datediff(dd,o.OrderDate,getdate()) as DateSinceLastPurchase
from[dbo].[Customer]c inner join [dbo].[Order] b on b.CustomerId = c.Id
join (select max(Id) as OrderId, min(Id) as minOrder,[CustomerId] from [dbo].[Order] group by [CustomerId])conn on c.Id = conn.[CustomerId]
join [dbo].[Order]o on o.[Id] = conn.OrderId
join [dbo].[Order]d on d.[Id] = conn.minOrder
--join [dbo].[OrderItem]b on = conn.OrderId
but i keep getting errors i am a beginner at this
Please note that I did not execute the query.
If you do not want that column please try the below query. I did not execute the query though
;WITH CTE_Temp
AS
(
SELECT max(Id) AS OrderId
, min(Id) AS minOrder
, [CustomerId]
FROM [dbo].[Order]
GROUP BY [CustomerId]
)
SELECT c.Id AS CustomerId
, c.FirstName + ' ' + c.LastName AS CustomerName
, DATENAME(MM, d.OrderDate) AS MonthofFirstPurchase
--,sum(d.TotalAmount) AS CummulativeValue
, d.OrderDate AS DateOfFirstPurchase
, Datediff(dd, o.OrderDate, getdate()) AS DateSinceLastPurchase
FROM [dbo].[Customer] c
INNER JOIN [dbo].[Order] b ON b.CustomerId = c.Id
INNER JOIN CTE_Temp conn ON c.Id = conn.[CustomerId]
INNER JOIN [dbo].[Order] o ON o.[Id] = conn.OrderId
INNER JOIN [dbo].[Order] d ON d.[Id] = conn.minOrder
If you need the sum(d.TotalAmount) AS CummulativeValue. Just try the query
;WITH CTE_Temp
AS
(
SELECT max(Id) AS OrderId
, min(Id) AS minOrder
, [CustomerId]
FROM [dbo].[Order]
GROUP BY [CustomerId]
),
CTE_TEMP1
AS
(
SELECT CTE_Temp.[CustomerId], sum(d.TotalAmount) TotalAmount AS CummulativeValue
FROM [dbo].[Order] d INNER JOIN CTE_Temp ON d.[Id] = CTE_Temp.minOrder
GROUP BY CTE_TEMP.[CustomerId]
)
SELECT c.Id AS CustomerId
, c.FirstName + ' ' + c.LastName AS CustomerName
, DATENAME(MM, d.OrderDate) AS MonthofFirstPurchase
,CTE_TEMP1.TotalAmount AS CummulativeValue
, d.OrderDate AS DateOfFirstPurchase
, Datediff(dd, o.OrderDate, getdate()) AS DateSinceLastPurchase
FROM [dbo].[Customer] c
INNER JOIN [dbo].[Order] b ON b.CustomerId = c.Id
INNER JOIN CTE_Temp conn ON c.Id = conn.[CustomerId]
INNER JOIN [dbo].[Order] o ON o.[Id] = conn.OrderId
INNER JOIN CTE_TEMP1 d ON d.CustomerId = c.id
I have modified the anser provided by Gopakumar and i came to the solution of the problem. The code below works perfectly well for its purpose
;WITH CTE_Temp
AS
(
SELECT max(Id) AS MaxOrder
, min(Id) AS MinOrder
, [CustomerId]
FROM [dbo].[Order]
GROUP BY [CustomerId]
),
CTE_TEMP1 AS(SELECT CTE_TEMP.CustomerId,sum([UnitQuantity]) AS UnitsPurchasedForMonth,sum(TotalAmount) AS ValueForMonth
from [dbo].[OrderItem]p left outer join [dbo].[Order] e on p.Id = e.Id
INNER JOIN CTE_Temp ON e.[Id] = CTE_Temp.minOrder GROUP BY CTE_TEMP.CustomerId),
CTE_TEMP2 AS(SELECT e.CustomerId,sum([UnitQuantity]) AS CummulativeUnitsPurchased,sum(TotalAmount) AS CummulativeValue
from [dbo].[OrderItem]p inner join [dbo].[Order] e on p.Id = e.Id group by e.CustomerId)
SELECT c.Id AS CustomerId
, c.FirstName + ' ' + c.LastName AS CustomerName
, DATENAME(MM, o.OrderDate) AS MonthofFirstPurchase
, o.OrderDate AS DateOfFirstPurchase
,d.ValueForMonth AS ValuePurchasedForMonth
,d.UnitsPurchasedForMonth
,e.CummulativeUnitsPurchased
,e.CummulativeValue
, Datediff(dd, a.OrderDate, getdate()) AS DateSinceLastPurchase
,EOMONTH(o.OrderDate) AS LastDayOfMonth
FROM [dbo].[Customer] c
INNER JOIN CTE_Temp conn ON c.Id = conn.CustomerId
INNER JOIN [dbo].[Order] o ON o.[Id] = conn.MinOrder
INNER JOIN CTE_TEMP1 d ON d.CustomerId = c.id
INNER JOIN [dbo].[Order] a on a.Id = conn.MaxOrder
inner join CTE_TEMP2 e on c.Id = e.CustomerId
you can edit as you like to get your results
tbi_Customer tbl_order
CustId int orderid int
Customer no OrderName varchar(50)
CustId int
try this
select top 1 a.customerno,b.totalorder from tbl_Customer as a
join (select custid,count(custid) as totalorder from tbl_order group by custid) b on a.custid=b.custid
order by b.totalorder desc
Since there is no OrderAmount type column, I am assuming what you need is maximum number of orders.
select top 1
C.[Customer Number],
count(C.[Customer Number]) as [Number of Orders]
from tbl_Customer C join tbl_order O
on C.CustId = O.CustId
group by C.[Customer Number]
order by 2 desc
I have an Employee table like this
And a second table for EmployeeComments with the EmployeeID as foreign key:
I would like to query the employees with their comments in the following format:
select Name, Comment
from Employee emp
left join EmployeeComments empC on empC.EmployeeID = emp.ID
I would like the results to be like:
I have already looked at Pivot, but it doesn't resolve my issue
Use window function:
select case when row_number() over(partition by emp.name order by empC.ID) = 1
then Name
else '' end as Name,
Comment
from Employee emp
left join EmployeeComments empC On empC.EmployeeID = emp.ID
This might give you some kind of order in your result window at least
WITH cte AS(
SELECT emp.Name ,
empC.Comment,
RANK() OVER (ORDER BY emp.Name) NameOrder,
ROW_NUMBER() OVER (PARTITION BY emp.Name ORDER BY empC.ID) RN
FROM Employee emp
LEFT JOIN EmployeeComments empC ON empC.EmployeeID = emp.ID
)
SELECT
Name = (CASE WHEN RN = 1 THEN Name ELSE '' END),
Comment
FROM
cte
ORDER BY
NameOrder,
RN
"use Cross Join:"
Query:
select case t.cnt
when 1 then
coalesce(t.Name,' ')
end as Name,t.comment
from
(
select t1.Name,t2.comment,row_number()
over(partition by t1.name order by t1.Name)
as cnt
from
EmployeeComments t1
cross join
Employee t2
where t1.ID=t2.Employeeid
)t
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)