Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 General SQL Server Forums
 New to SQL Server Programming
 Query Help : Who quoted highest price?

Author  Topic 

shaheedfazal
Starting Member

6 Posts

Posted - 2010-09-15 : 13:12:25
Hi,

I am trying to create a query in SQL Server 2005 that looks at all the prices that we have been quoted this month and selects the max price and the corresponding customer. I managed to come up with the following query:

Select
All_Quotes_This_Month.PipCode,
Max(All_Quotes_This_Month.Price),
All_Quotes_This_Month.Customer
From
(Select
Month(SO_SalesOrder.OrderDate) As OrderDate,
BASE_Product.Name As PipCode,
BASE_Product.Description As Description,
SO_SalesOrder_Line.Quantity As Quantity,
SO_SalesOrder_Line.UnitPrice As Price,
BASE_Customer.Name As Customer,
SO_SalesOrder.Custom2
From
SO_SalesOrder Inner Join
SO_SalesOrder_Line On SO_SalesOrder.SalesOrderId =
SO_SalesOrder_Line.SalesOrderId Inner Join
BASE_Product On BASE_Product.ProdId = SO_SalesOrder_Line.ProdId Inner Join
BASE_Customer On BASE_Customer.CustomerId = SO_SalesOrder.CustomerId
Where
Month(SO_SalesOrder.OrderDate) = Month(GetDate()) And
SO_SalesOrder.OrderStatus <> 10 And
Year(SO_SalesOrder.OrderDate) = Year(GetDate()) And
SO_SalesOrder.Custom2 = 'Y') All_Quotes_This_Month
Group By
All_Quotes_This_Month.PipCode, All_Quotes_This_Month.Customer
Having
Max(All_Quotes_This_Month.Price) = Max(All_Quotes_This_Month.Price)


The problem with this query is that it returns the max price for every customer. So for example, it returns the following data (have removed the other fields below for the sake of simplicity:

PIPCode,Price,Customer
1,1,A
1,2,B
1,3,C
2,3,A
2,4,B
2,5,C

I want it to only show

PIPCode,Price,Customer
1,3,C
2,5,C

Where am I going wrong?

Shaheed

jcelko
Esteemed SQL Purist

547 Posts

Posted - 2010-09-15 : 14:22:58
>> I am trying to create a query in SQL Server 2005 that looks at all the prices that we have been quoted this month and selects the max price and the corresponding customer. I managed to come up with the following query: <<

Your code is very hard to read. Data elements have vague names, like "name" and "description" and "quantity" instead of being precise and usable. Your tables are singular, so we know you have only one row in them; if they were sets of rows, the names would be plural or collective nouns. You give aliases that are the same as the column name. The same data element has multiple names (i.e. name is also the same as pip_code; that violates basic data modeling since codes are not names).

I have cleaned it up a bit, following ISO-1179 rules for data elements, dropping columns that are not used and making guesses without any DDL.

SELECT MQ.pip_code, MQ.product_description, MQ.unit_price, MQ.customer_name
FROM (SELECT MONTH(SO.order_date) AS order_month,
BP.pip_code, BP.product_description,
SOL.order_line_qty, SOL.unit_price,
BC.customer_name,
SO.custom2_flg
FROM SO_SalesOrders AS SO,
SO_SalesOrder_Lines AS SOL,
BASE_Products AS BP,
BASE_Customers AS BC
WHERE SO.sales_order_id = SOL.sales_order_id
AND BP.prod_id= SOL.prod_id
AND BC.customer_id = SO.customer_id
AND MONTH(SO.order_date) = MONTH(CURRENT_TIMESTAMP)
AND SO.order_status <> 10
AND YEAR(SO.order_date) = YEAR(CURRENT_TIMESTAMP)
AND SO.custom2 = 'Y')
AS MQ
GROUP BY MQ.pip_code, MQ.description, MQ.customer
HAVING MQ.unit_price = MAX(MQ.unit_price);

I cannot figure out name versus pip_code versus prod_id. Isn't there a UPC, SKU or some industry standard to identify products?

SQL is a database language, not a computational language. We hate functions and love joins and predicates. First build a table of reporting periods, something like this:

CREATE TABLE ReportPeriods
(report_period_name CHAR(10) NOT NULL PRIMARY KEY,
report_period_start_date DATE NOT NULL,
report_period_end_date DATE NOT NULL,
CHECK (report_period_start_date < report_period_end_date));

>> The problem with this query is that it returns the max price for every customer. So for example, it returns the following data (have removed the other fields [sic: columns are not fields] below for the sake of simplicity: ..<<

I am guessing that you want the greatest unit price paid and not the largest total order amount. I am also guessing that you need to handle ties if you have two or more customers who over-pay in a month.

Here is my guess. Give it the month (@in_report_period_name) and the number of top customers (@in_top_n)you want to see

WITH MQ (pip_code, unit_price, customer_name, unit_price_rank)
AS
(SELECT BP.pip_code, SOL.unit_price, BC.customer_name,
DENSE_RANK()
OVER (PARTITION BY BP.pip_code
ORDER BY SOL.unit_price DESC)
AS unit_price_rank
FROM SO_SalesOrders AS SO,
SO_SalesOrder_Lines AS SOL,
BASE_Customers AS BC,
BASE_Products AS BP,
ReportPeriods AS RP
WHERE SO.sales_order_id = SOL.sales_order_id
AND BP.prod_id = SOL.prod_id
AND BC.customer_id = SO.customer_id
AND SO.order_status <> 10
AND SO.custom2_flg = 'Y'
AND SO.order_date
BETWEEN RP.report_period_start_date AND RP.report_period_end_date
AND RP.report_period_name = @in_report_period_name)

SELECT pip_code, unit_price, customer_name
FROM MQ
WHERE unit_price_rank <= @in_top_n;


--CELKO--
Books in Celko Series for Morgan-Kaufmann Publishing
Analytics and OLAP in SQL
Data and Databases: Concepts in Practice
Data, Measurements and Standards in SQL
SQL for Smarties
SQL Programming Style
SQL Puzzles and Answers
Thinking in Sets
Trees and Hierarchies in SQL
Go to Top of Page

shaheedfazal
Starting Member

6 Posts

Posted - 2010-09-16 : 07:28:09
Thanks Celco for your response. I didn't know one didn't need to use joins in derived tables. Thanks for cleaning up the code. The naming conventions aren't mine (I am just querying the database of our stock control system). I put your query into the format of my stock control system and ended up with the following (Name is SKU/PipCode):

SELECT
MQ.PipCode,
MQ.Description,
MQ.Price,
MQ.Customer,
MQ.Quantity
From
(Select
Month(SO_SalesOrder.OrderDate) As OrderMonth,
BASE_Product.Name As PipCode,
BASE_Product.Description As Description,
SO_SalesOrder_Line.Quantity As Quantity,
SO_SalesOrder_Line.UnitPrice As Price,
BASE_Customer.Name As Customer
From
BASE_Product Inner Join
SO_SalesOrder_Line On BASE_Product.ProdId = SO_SalesOrder_Line.ProdId
Inner Join
SO_SalesOrder On SO_SalesOrder.SalesOrderId =
SO_SalesOrder_Line.SalesOrderId Inner Join
BASE_Customer On BASE_Customer.CustomerId = SO_SalesOrder.CustomerId
Where
SO_SalesOrder.SalesOrderId = SO_SalesOrder_Line.SalesOrderId And
BASE_Product.ProdId = SO_SalesOrder_Line.ProdId And
BASE_Customer.CustomerId = SO_SalesOrder.CustomerId And
(Month(SO_SalesOrder.OrderDate) = Month(Current_TimeStamp) And
SO_SalesOrder.OrderStatus <> 10 And
SO_SalesOrder.Custom2 = 'Y' And
Year(SO_SalesOrder.OrderDate) = Year(Current_TimeStamp))) MQ
Group By
MQ.PipCode, MQ.Description, MQ.Customer, MQ.Quantity, MQ.Price
HAVING MQ.Price = MAX(MQ.Price)

You will note that I had to group by more fields than you had specified in your original query as I kept getting the 'is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause' error.

When I run this query I get all the prices quoted by all the customers throughout the month (see example):

002-1584,Product1,3.17000,Cust1,500.0000
002-1584,Product1,3.79000,Cust2,50.0000
002-1584,Product1,4.30000,Cust3,1.0000
002-1584,Product1,3.65000,Cust4 ,1.0000
002-1584,Product1,3.50000,Cust5,100.0000
002-1584,Product1,3.80000,Cust6,100.0000
002-1584,Product1,4.50000,Cust7,20.0000

All I wanted was the highest price for each product and which customer quoted it.

002-1584,Product1,4.50000,Cust7,20.0000

Obviously there are over 200 products but the example above should suffice.

Are you saying that I have to create the report table in order to get this? I am very inexperienced with SQL and I don't want to mess up the database of the stock control system as I haven't designed it. Also my primary purpose is to get this information into excel for help in our price negotiation process and this seems awfully complicated just to do a simple task.

Is there a way to keep it simple?
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2010-09-16 : 12:41:03
see scenario 2 in

http://visakhm.blogspot.com/search/label/cross%20apply

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page

shaheedfazal
Starting Member

6 Posts

Posted - 2010-09-17 : 05:18:40
It's not clear from your post how this would apply to my scenario as you are only dealing with two tables. Are you saying that I should create a list of all prices quoted this month and then cross apply the customer?
Go to Top of Page

rohitvishwakarma
Posting Yak Master

232 Posts

Posted - 2010-09-17 : 09:24:23
try this:


Select
Month(SO_SalesOrder.OrderDate) As OrderMonth,
BASE_Product.Name As PipCode,
BASE_Product.Description As Description,
SO_SalesOrder_Line.Quantity As Quantity,
SO_SalesOrder_Line.UnitPrice As Price,
BASE_Customer.Name As Customer
INTO #temp
From BASE_Product
Inner Join SO_SalesOrder_Line
On BASE_Product.ProdId = SO_SalesOrder_Line.ProdId
Inner Join SO_SalesOrder
On SO_SalesOrder.SalesOrderId = SO_SalesOrder_Line.SalesOrderId
Inner Join BASE_Customer
On BASE_Customer.CustomerId = SO_SalesOrder.CustomerId
Where
SO_SalesOrder.SalesOrderId = SO_SalesOrder_Line.SalesOrderId And
BASE_Product.ProdId = SO_SalesOrder_Line.ProdId And
BASE_Customer.CustomerId = SO_SalesOrder.CustomerId And
(Month(SO_SalesOrder.OrderDate) = Month(Current_TimeStamp) And
SO_SalesOrder.OrderStatus <> 10 And
SO_SalesOrder.Custom2 = 'Y' And
Year(SO_SalesOrder.OrderDate) = Year(Current_TimeStamp))



and you will get the o/p from fol query:




SELECT A.PipCode,B.Description,A.MaxPrice,B.Customer, B.Quantity FROM
(
SELECT PipCode,MAX(Price) AS MaxPrice FROM #temp GROUP BY PipCode
)A
INNER JOIN
(
SELECT OrderMonth,PipCode,Description,Quantity,Price,Customer FROM #temp
)B
ON A.PipCode = B.PipCode AND A.MaxPrice = B.Price


Thanks
Rohit
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2010-09-17 : 11:46:33
quote:
Originally posted by shaheedfazal

It's not clear from your post how this would apply to my scenario as you are only dealing with two tables. Are you saying that I should create a list of all prices quoted this month and then cross apply the customer?


first take data based on PIPCode and then cross apply on top 1 record based on ORDER BY Price DESC for that PIPCode

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page

shaheedfazal
Starting Member

6 Posts

Posted - 2010-09-20 : 06:21:50
Rohit,

Thanks for your help. Your solution was very easy to understand for a novice like me. I built on the information you sent me by first creating a view with the following columns:

OrderMonth
PipCode
Description
Quantity
Price
Customer

NB: This view only contains data from the last three months.

I then proceeded to try and run a query that would return the following information:

PipCode,Description,HighestPriceLast3Months,Buyerquotinghighestprice, Monthbuyerquotedprice

I used the following syntax:

SELECT distinct A.PipCode,b.Description,A.MaxPrice as HighestPriceLast3Months,B.Customer as buyerquotinghighestprice,B.OrderMonth as monthbuyerquotedprice FROM
(
SELECT PipCode,MAX(Price) AS MaxPrice FROM AllQuotesLast3Months GROUP BY PipCode
)A
INNER JOIN
(
SELECT PipCode,Description,Price,Customer,ordermonth FROM AllQuotesLast3Months
)B
ON A.PipCode = B.PipCode AND A.MaxPrice = B.Price
Order by b.description asc

Inevitably there are ties on a number of products with either the customer or the order month being duplicated. Is there a way that I can combine the two records into one? For example, if I have the following data:

Code,Description,HighestPriceLast3Months,Buyerquotinghighestprice, Monthbuyerquotedprice
27 Product1 43 A August
27 Product1 43 A September
27 Product1 43 B August
27 Product1 43 B September
27 Product1 43 C September
27 Product1 43 D August

I want to handle the date by showing the most recent one and then separate each buyer with a '/'. So the output I want to create is:

27 Product1 43 A/B/C September

Your help is much appreciated. I am learning a lot.

Shaheed
Go to Top of Page

rohitvishwakarma
Posting Yak Master

232 Posts

Posted - 2010-09-20 : 07:42:18
Hi shaheedfazal,

suppose you are getting o/p like:

Code,Description,HighestPriceLast3Months,Buyerquotinghighestprice, Monthbuyerquotedprice
27 Product1 43 A August
27 Product1 43 A September
27 Product1 43 B August
27 Product1 43 B September
27 Product1 43 C September
27 Product1 43 D August

using the query:

SELECT distinct A.PipCode,b.Description,A.MaxPrice as HighestPriceLast3Months,B.Customer as buyerquotinghighestprice,B.OrderMonth as monthbuyerquotedprice FROM
(
SELECT PipCode,MAX(Price) AS MaxPrice FROM AllQuotesLast3Months GROUP BY PipCode
)A
INNER JOIN
(
SELECT PipCode,Description,Price,Customer,ordermonth FROM AllQuotesLast3Months
)B
ON A.PipCode = B.PipCode AND A.MaxPrice = B.Price
Order by b.description asc

What you need to do is as follows:

1) Filter out the record for Latest Month

SELECT ....INTO #temp FROM
(
SELECT PipCode,MAX(Price) AS MaxPrice FROM AllQuotesLast3Months GROUP BY PipCode
)A
INNER JOIN
(
SELECT PipCode,Description,Price,Customer,ordermonth FROM AllQuotesLast3Months
)B
ON A.PipCode = B.PipCode AND A.MaxPrice = B.Price
WHERE = some condn to get the latest month
Order by b.description asc

2) Now, as per the sample data your records in #temp will be:

Code,Description,HighestPriceLast3Months,Buyerquotinghighestprice, Monthbuyerquotedprice
27 Product1 43 A September
27 Product1 43 B September
27 Product1 43 C September


3) Create temporary table like this

CREATE TABLE #temp_customers
(
id INT IDENTITY(1,1),
customers VARCHAR(50)
)

4)

Insert distinct Customers from #temp into #temp_customers
as :

INSERT INTO #temp_customers
SELECT DISTINCT Buyerquotinghighestprice FROM #temp

5) Data in #temp_customers should look like:
id customers
1 A
2 B
3 C

6) Do the Following:

DECLARE @customers VACRHAR(1000)
DECLARE @count INT
DECLARE @max_count INT

SET @count = 1
SELECT @max_count = MAX(id) FROM #temp_customers

WHILE (@count < @max_count)
BEGIN
IF(@count = 1)
SET @customers = (SELECT customers FROM #temp_customers WHERE id = @count)
ELSE
SET @customers = @customers + '/' + (SELECT customers FROM #temp_customers WHERE id = @count)

SET @count = @count + 1
END

7) Data in @customers = 'A/B/C'
8) To Display

SELECT TOP 1 Code,Description,HighestPriceLast3Months,@customers AS Buyerquotinghighestprice, Monthbuyerquotedprice FROM #temp
WHERE some condn to get the latest month

Thanks

Rohit
Go to Top of Page

shaheedfazal
Starting Member

6 Posts

Posted - 2010-09-20 : 11:28:51
Hi Rohit,

I used the following syntax:

drop table #temp
drop table #temp_customers
Select Distinct
A.PipCode,
B.Description,
A.MaxPrice As HighestPriceLast3Months,
B.Customer As buyerquotinghighestprice,
B.OrderMonth As monthbuyerquotedprice
INTO #temp
From
(Select
AllQuotesLast3Months.PipCode,
Max(AllQuotesLast3Months.Price) As MaxPrice,
Max(OrderMonth) as MaxDate
From
AllQuotesLast3Months
Group By
AllQuotesLast3Months.PipCode) A Inner Join
(Select
AllQuotesLast3Months.PipCode,
AllQuotesLast3Months.Description,
AllQuotesLast3Months.Price,
AllQuotesLast3Months.Customer,
AllQuotesLast3Months.OrderMonth
From
AllQuotesLast3Months) B On A.PipCode = B.PipCode And A.MaxPrice = B.Price AND A.MaxDate = B.OrderMonth
Group By
A.PipCode, B.Description, A.MaxPrice, B.Customer, B.OrderMonth
Order By
B.Description
CREATE TABLE #temp_customers
(
id INT IDENTITY(1,1),
customers VARCHAR(50)
)
INSERT INTO #temp_customers
SELECT DISTINCT Buyerquotinghighestprice FROM #temp
DECLARE @customers VACRHAR(1000)
DECLARE @count INT
DECLARE @max_count INT

SET @count = 1
SELECT @max_count = MAX(id) FROM #temp_customers

WHILE (@count < @max_count)
BEGIN
IF(@count = 1)
SET @customers = (SELECT customers FROM #temp_customers WHERE id = @count)
ELSE
SET @customers = @customers + '/' + (SELECT customers FROM #temp_customers WHERE id = @count)

SET @count = @count + 1
END

I have run into the following error:

Msg 2715, Level 16, State 3, Line 53
Column, parameter, or variable #3: Cannot find data type VACRHAR.
Parameter or variable '@customers' has an invalid data type.

I don't understand why this error is coming up as VARCHAR is a normal data type in sql?

Go to Top of Page

rohitvishwakarma
Posting Yak Master

232 Posts

Posted - 2010-09-20 : 11:35:56
quote:
Originally posted by shaheedfazal

Hi Rohit,

DECLARE @customers VACRHAR(1000)
DECLARE @count INT
DECLARE @max_count INT

SET @count = 1
SELECT @max_count = MAX(id) FROM #temp_customers

WHILE (@count < @max_count)
BEGIN
IF(@count = 1)
SET @customers = (SELECT customers FROM #temp_customers WHERE id = @count)
ELSE
SET @customers = @customers + '/' + (SELECT customers FROM #temp_customers WHERE id = @count)

SET @count = @count + 1
END

I have run into the following error:

Msg 2715, Level 16, State 3, Line 53
Column, parameter, or variable #3: Cannot find data type VACRHAR.
Parameter or variable '@customers' has an invalid data type.

I don't understand why this error is coming up as VARCHAR is a normal data type in sql?






VARCHAR
Go to Top of Page

shaheedfazal
Starting Member

6 Posts

Posted - 2010-09-20 : 12:18:43
Doh! That was very silly of me!

I'm almost there but the suggestion you made for the next part does not seem to produce the desired result:

SELECT TOP 1000 PipCode,Description,HighestPriceLast3Months,@customers AS Buyerquotinghighestprice, Monthbuyerquotedprice FROM #temp
group by pipcode, description,HighestPriceLast3Months,Buyerquotinghighestprice,Monthbuyerquotedprice
order by description

This puts A/B/C in every row when it could be that some are A/B others are just C etc.

Also, I'm still getting duplicate records e.g:

27 Product1 43.70000 A/B/C/D/E/F/G 9
27 Product1 43.70000 A/B/C/D/E/F/G 9
27 Product1 43.70000 A/B/C/D/E/F/G 9

Any ideas?
Go to Top of Page

jcelko
Esteemed SQL Purist

547 Posts

Posted - 2010-09-20 : 15:17:36
>> You will note that I had to group by more fields [sic: columns are not fields] than you had specified in your original query .. <<

Let's clean it up again. The outer query is not needed and just cost time to materialize it. I will not even try to fix the data elements this time, tho this will kill a system in the long run.

SELECT SO.orderdate, BP.name AS pipcode,
BP.description, SOL.quantity, BC.name AS customer_name,
MAX(SOL.unitprice) AS sucker_price -- needs a funnier name
FROM Base_Products AS BP,
SO_Salesorder AS SO,
SO_Salesorder_Line AS SOL,
Base_Customer AS BC,
Report_Periods AS RP
WHERE BP.prodid = SOL.prodid
AND BC.customerid = SO.customerid
AND SO.salesorderid = SOL.salesorderid
AND BC.customerid = SO.customerid
AND O.orderdate
BETWEEN RP.report_period_start_date AND RP.report_period_end_date
AND SO.orderstatus <> 10
AND SO.custom2 = 'Y'
AND RP.report_period_name = @in_report_period
GROUP BY SO.orderdate, BP.name, BP.description, SOL.quantity, BC.name;

Alias table names make code so much easier to read. Consistent capitalization is important -- keywords in uppercase, scalars in lowercase and objects capitalized.

>> (Name is SKU/PipCode) <<

And it is also a customer name! You have no data dictionary or control over this thing. So we have to alias the two "name" columns in the SELECT.

>> I didn't know one didn't need to use joins in derived tables. <<

A derived table can be used anywhere a table can be used and written the same as any SELECT. The Report Periods table is called an auxiliary table, by the way. I don't like the infixed INNER JOIN notation; look at your code and find the duplicated predicates.

>> The naming conventions aren't mine (I am just querying the database of our stock control system). <<

Sorry about that. They are not anybody's standards. After a few decades in SQL, you recognize the symptoms of a bad database. You have a lot of symptoms; keep the resume updated, just in case :)

>> Are you saying that I have to create the report table in order to get this? <<

No, I am saying that a report period table will make your code run one or two orders of magnitude faster, help assure that all report are done the same way, be portable and be maintainable. SQL is not a computational language; we hate functions, loops, recursion and all that stuff. We want joins.

Why is the unit price in the sales order details and not in the Base Product (inventory?) table? Do you give each occurrence of a product in each line of any order a different unit price? Why did you get the pip code from Base Products and not from the order line (you should have a REFERENCES back to the Base Products, so it is known to be valid)?

Yes, SQL takes a long time to learn well. Start using the right words so you will develop the right mindset. Think in sets, not procedures.




--CELKO--
Books in Celko Series for Morgan-Kaufmann Publishing
Analytics and OLAP in SQL
Data and Databases: Concepts in Practice
Data, Measurements and Standards in SQL
SQL for Smarties
SQL Programming Style
SQL Puzzles and Answers
Thinking in Sets
Trees and Hierarchies in SQL
Go to Top of Page

rohitvishwakarma
Posting Yak Master

232 Posts

Posted - 2010-09-21 : 03:48:51
My mistake I ignored one important thing while filling the #temp_customers table

INSERT INTO #temp_customers
SELECT DISTINCT Buyerquotinghighestprice FROM #temp

It will populate with all the customers which is wrong.

I have modified the query a little bit which is as follows:


First one is:

1)

SELECT
Month(SO_SalesOrder.OrderDate) As OrderMonth,
BASE_Product.Name As PipCode,
BASE_Product.Description As Description,
SO_SalesOrder_Line.Quantity As Quantity,
SO_SalesOrder_Line.UnitPrice As Price,
BASE_Customer.Name As Customer
INTO #temp
FROM BASE_Product
Inner Join SO_SalesOrder_Line
On BASE_Product.ProdId = SO_SalesOrder_Line.ProdId
Inner Join SO_SalesOrder
On SO_SalesOrder.SalesOrderId = SO_SalesOrder_Line.SalesOrderId
Inner Join BASE_Customer
On BASE_Customer.CustomerId = SO_SalesOrder.CustomerId
Where
SO_SalesOrder.SalesOrderId = SO_SalesOrder_Line.SalesOrderId And
BASE_Product.ProdId = SO_SalesOrder_Line.ProdId And
BASE_Customer.CustomerId = SO_SalesOrder.CustomerId And
(Month(SO_SalesOrder.OrderDate) = Month(Current_TimeStamp) And
SO_SalesOrder.OrderStatus <> 10 And
SO_SalesOrder.Custom2 = 'Y' And
Year(SO_SalesOrder.OrderDate) = Year(Current_TimeStamp))


2)
 
CREATE TABLE #temp_customers
(
id INT IDENTITY(1,1),
PipCode VARCHAR(100),
customers VARCHAR(50)
)


3)

INSERT INTO #temp_customers
SELECT A.PipCode,B.Customer FROM
(
SELECT PipCode,MAX(Price) AS MaxPrice FROM #temp GROUP BY PipCode
)A
INNER JOIN
(
SELECT PipCode,Description,Price,Customer,ordermonth FROM #temp
)B
ON A.PipCode = B.PipCode AND A.MaxPrice = B.Price
ORDER BY b.description ASC


4)

CREATE TABLE #temp_Customers_combined
(
PipCode VARCHAR(100),
customers VARCHAR(1000)
)


5)

DECLARE @count_outer INT
DECLARE @max_count_outer INT

SET @count_outer = 1
SELECT @max_count_outer = (SELECT COUNT(DISTINCT PipCode) FROM #temp_customers)


6)

WHILE(@count_outer <= @max_count_outer)
BEGIN
DECLARE @pip_code VARCHAR(100)
DECLARE @customers VARCHAR(1000)
DECLARE @count INT
DECLARE @max_count INT

SET @customers = ''
SELECT @pip_code = PipCode FROM #temp_customers WHERE id = @count_outer

SELECT @count = MIN(id) FROM #temp_customers WHERE PipCode = @pip_code
SELECT @max_count = MAX(id) FROM #temp_customers WHERE PipCode = @pip_code

WHILE (@count <= @max_count)
BEGIN
IF(LEN(@customers) = 0)
SET @customers = (SELECT customers FROM #temp_customers WHERE id = @count AND PipCode = @pip_code)
ELSE
SET @customers = @customers + '/' + (SELECT customers FROM #temp_customers WHERE id = @count AND PipCode = @pip_code)

SET @count = @count + 1
END

INSERT INTO #temp_Customers_combined
SELECT @pip_code,@customers
SET @customers = ''
SET @count_outer = @count_outer + 1
END


7)


SELECT TOP 1000 T.PipCode,Description,MAX(Price),C.customers AS Buyerquotinghighestprice, OrderMonth FROM #temp T
INNER JOIN #temp_Customers_combined C
ON T.PipCode = C.PipCode
group by T.pipcode, description,OrderMonth,C.customers
order by description



Exectue all the above at once and you will get the desired result. Hope, it is correct if not, post here.

Thanks
Rohit
Go to Top of Page

rohitvishwakarma
Posting Yak Master

232 Posts

Posted - 2010-09-21 : 05:40:44
I will explain you the queries with some sample data:

Following is the sample data:
Code,Description,HighestPriceLast3Months,Buyerquotinghighestprice, Monthbuyerquotedprice
27 Product1 43 A August
27 Product1 43 A September
27 Product1 43 B August
29 Product2 83 B September
27 Product1 43 C September
27 Product1 43 D August
29 Product2 77 E August
29 Product2 83 E September
30 Product3 90 F September
30 Product3 90 A August

#1

You already know what it is going to produce, It will display you the products, price and customers for the current month because of this condition in WHERE clause:
Where
SO_SalesOrder.SalesOrderId = SO_SalesOrder_Line.SalesOrderId And
BASE_Product.ProdId = SO_SalesOrder_Line.ProdId And
BASE_Customer.CustomerId = SO_SalesOrder.CustomerId And
(Month(SO_SalesOrder.OrderDate) = Month(Current_TimeStamp) And
SO_SalesOrder.OrderStatus <> 10 And
SO_SalesOrder.Custom2 = 'Y' And
Year(SO_SalesOrder.OrderDate) = Year(Current_TimeStamp))

so, your o/p will be:

Code,Description,HighestPriceLast3Months,Buyerquotinghighestprice, Monthbuyerquotedprice
27 Product1 43 A September
29 Product2 83 B September
27 Product1 43 C September
29 Product2 83 E September
30 Product3 90 F September

#2

Creates a temp table '#temp_customers'
to hold the customers alongwith the productcode they quoted for and an autoincrement column 'id' which we will use in WHILE Loop in step #6

#3

Populates the table '#temp_customers' with customers who quoted the highest price for a product.
You can put this line: SELECT * FROM #temp_customers after #3 to verify the data. Based on our sample data above the contents of #temp_customers will be

id , PipCode , customers
1 27 A
2 27 C
3 29 B
4 29 E
5 30 F
* Tie between A & C for product code 27
* Tie between B & E for product code 29
* F is the only customer for Product code 30

#4

Creates the table #temp_Customers_combined to hold the customers seperated with '/'

#5

Declares and Sets the loop variables

SET @count_outer = 1
SELECT @max_count_outer = (SELECT COUNT(DISTINCT PipCode) FROM #temp_customers)


@max_count_outer will hold the number of distinct Productcodes in the table #temp_customers

for our sample data it will be 3

6

The outer WHILE Loop will loop for the Product Codes and the inner WHILE will gather the repective customers.
read the comments alonghwith the code(highlighted in GREEN)


WHILE(@count_outer <= @max_count_outer) -- for 1 to 3 (product codes)
BEGIN
DECLARE @pip_code VARCHAR(100)
DECLARE @customers VARCHAR(1000)
DECLARE @count INT -- counter for nested WHILE LOOP
DECLARE @max_count INT -- counter for nested WHILE LOOP

SET @customers = ''
SELECT @pip_code = PipCode FROM #temp_customers WHERE id = @count_outer--Get the code using the id

SELECT @count = MIN(id) FROM #temp_customers WHERE PipCode = @pip_code --start frm Min id of the code
SELECT @max_count = MAX(id) FROM #temp_customers WHERE PipCode = @pip_code -- go till Max id of the code

WHILE (@count <= @max_count)
BEGIN
IF(LEN(@customers) = 0)
SET @customers = (SELECT customers FROM #temp_customers WHERE id = @count AND PipCode = @pip_code)
ELSE
SET @customers = @customers + '/' + (SELECT customers FROM #temp_customers WHERE id = @count AND PipCode = @pip_code)

SET @count = @count + 1
END
--Customers are set in @customers seperated by '/'
INSERT INTO #temp_Customers_combined
SELECT @pip_code,@customers
--above will fill the table #temp_Customers_combined

SET @customers = ''
SET @count_outer = @count_outer + 1
END



based on our sample data the table #temp_Customers_combined will hold
PipCode , Customers
27 A/C
29 B/E
30 F

#7

Finally using the JOIN between tables #temp_Customers_combined & #temp (from #1) you will get the result as:

PipCode , Description , MAX(Price) , customers, OrderMonth
27 Product1 43 A/C September
29 Product2 83 B/E September
30 Product3 90 F September


* I have tested the query with 3 products and is giving me correct results.

I hope i have explained the basic logic behind the query & the query gives you the desired Output.

Thanks
Rohit
Go to Top of Page
   

- Advertisement -