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.
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.CustomerFrom (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_MonthGroup By All_Quotes_This_Month.PipCode, All_Quotes_This_Month.CustomerHaving 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,Customer1,1,A1,2,B1,3,C2,3,A2,4,B2,5,CI want it to only showPIPCode,Price,Customer1,3,C2,5,CWhere 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.customerHAVING 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 seeWITH 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 PublishingAnalytics and OLAP in SQLData and Databases: Concepts in Practice Data, Measurements and Standards in SQLSQL for SmartiesSQL Programming Style SQL Puzzles and Answers Thinking in SetsTrees and Hierarchies in SQL |
|
|
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.QuantityFrom (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))) MQGroup By MQ.PipCode, MQ.Description, MQ.Customer, MQ.Quantity, MQ.PriceHAVING 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.0000002-1584,Product1,3.79000,Cust2,50.0000002-1584,Product1,4.30000,Cust3,1.0000002-1584,Product1,3.65000,Cust4 ,1.0000002-1584,Product1,3.50000,Cust5,100.0000002-1584,Product1,3.80000,Cust6,100.0000002-1584,Product1,4.50000,Cust7,20.0000All I wanted was the highest price for each product and which customer quoted it. 002-1584,Product1,4.50000,Cust7,20.0000Obviously 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? |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2010-09-16 : 12:41:03
|
see scenario 2 inhttp://visakhm.blogspot.com/search/label/cross%20apply------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
|
|
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? |
|
|
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 |
|
|
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 MVPhttp://visakhm.blogspot.com/ |
|
|
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:OrderMonthPipCodeDescriptionQuantityPriceCustomerNB: 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, MonthbuyerquotedpriceI 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.PriceOrder by b.description ascInevitably 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, Monthbuyerquotedprice27 Product1 43 A August27 Product1 43 A September27 Product1 43 B August27 Product1 43 B September27 Product1 43 C September27 Product1 43 D AugustI 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 SeptemberYour help is much appreciated. I am learning a lot.Shaheed |
|
|
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, Monthbuyerquotedprice27 Product1 43 A August27 Product1 43 A September27 Product1 43 B August27 Product1 43 B September27 Product1 43 C September27 Product1 43 D Augustusing 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)BON A.PipCode = B.PipCode AND A.MaxPrice = B.PriceOrder by b.description ascWhat you need to do is as follows:1) Filter out the record for Latest MonthSELECT ....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)BON A.PipCode = B.PipCode AND A.MaxPrice = B.PriceWHERE = some condn to get the latest monthOrder by b.description asc2) Now, as per the sample data your records in #temp will be: Code,Description,HighestPriceLast3Months,Buyerquotinghighestprice, Monthbuyerquotedprice27 Product1 43 A September27 Product1 43 B September27 Product1 43 C September3) Create temporary table like thisCREATE TABLE #temp_customers(id INT IDENTITY(1,1),customers VARCHAR(50))4)Insert distinct Customers from #temp into #temp_customersas :INSERT INTO #temp_customersSELECT DISTINCT Buyerquotinghighestprice FROM #temp5) Data in #temp_customers should look like:id customers1 A2 B3 C6) Do the Following:DECLARE @customers VACRHAR(1000)DECLARE @count INTDECLARE @max_count INTSET @count = 1SELECT @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 + 1END7) Data in @customers = 'A/B/C'8) To DisplaySELECT TOP 1 Code,Description,HighestPriceLast3Months,@customers AS Buyerquotinghighestprice, Monthbuyerquotedprice FROM #tempWHERE some condn to get the latest monthThanks Rohit |
|
|
shaheedfazal
Starting Member
6 Posts |
Posted - 2010-09-20 : 11:28:51
|
Hi Rohit,I used the following syntax:drop table #tempdrop table #temp_customersSelect Distinct A.PipCode, B.Description, A.MaxPrice As HighestPriceLast3Months, B.Customer As buyerquotinghighestprice, B.OrderMonth As monthbuyerquotedpriceINTO #tempFrom (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.OrderMonthOrder By B.DescriptionCREATE TABLE #temp_customers(id INT IDENTITY(1,1),customers VARCHAR(50))INSERT INTO #temp_customersSELECT DISTINCT Buyerquotinghighestprice FROM #tempDECLARE @customers VACRHAR(1000)DECLARE @count INTDECLARE @max_count INTSET @count = 1SELECT @max_count = MAX(id) FROM #temp_customers WHILE (@count < @max_count)BEGINIF(@count = 1)SET @customers = (SELECT customers FROM #temp_customers WHERE id = @count) ELSESET @customers = @customers + '/' + (SELECT customers FROM #temp_customers WHERE id = @count)SET @count = @count + 1ENDI have run into the following error:Msg 2715, Level 16, State 3, Line 53Column, 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? |
|
|
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 INTDECLARE @max_count INTSET @count = 1SELECT @max_count = MAX(id) FROM #temp_customers WHILE (@count < @max_count)BEGINIF(@count = 1)SET @customers = (SELECT customers FROM #temp_customers WHERE id = @count) ELSESET @customers = @customers + '/' + (SELECT customers FROM #temp_customers WHERE id = @count)SET @count = @count + 1ENDI have run into the following error:Msg 2715, Level 16, State 3, Line 53Column, 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 |
|
|
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 #tempgroup by pipcode, description,HighestPriceLast3Months,Buyerquotinghighestprice,Monthbuyerquotedpriceorder by descriptionThis 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 927 Product1 43.70000 A/B/C/D/E/F/G 927 Product1 43.70000 A/B/C/D/E/F/G 9Any ideas? |
|
|
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 PublishingAnalytics and OLAP in SQLData and Databases: Concepts in Practice Data, Measurements and Standards in SQLSQL for SmartiesSQL Programming Style SQL Puzzles and Answers Thinking in SetsTrees and Hierarchies in SQL |
|
|
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 tableINSERT INTO #temp_customersSELECT DISTINCT Buyerquotinghighestprice FROM #tempIt 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_customersSELECT 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)BON A.PipCode = B.PipCode AND A.MaxPrice = B.PriceORDER BY b.description ASC 4)CREATE TABLE #temp_Customers_combined( PipCode VARCHAR(100), customers VARCHAR(1000)) 5)DECLARE @count_outer INTDECLARE @max_count_outer INTSET @count_outer = 1SELECT @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 TINNER JOIN #temp_Customers_combined C ON T.PipCode = C.PipCodegroup by T.pipcode, description,OrderMonth,C.customersorder by description Exectue all the above at once and you will get the desired result. Hope, it is correct if not, post here.ThanksRohit |
|
|
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, Monthbuyerquotedprice27 Product1 43 A August27 Product1 43 A September27 Product1 43 B August29 Product2 83 B September27 Product1 43 C September27 Product1 43 D August29 Product2 77 E August29 Product2 83 E September30 Product3 90 F September30 Product3 90 A August#1You 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, Monthbuyerquotedprice27 Product1 43 A September29 Product2 83 B September27 Product1 43 C September29 Product2 83 E September30 Product3 90 F September#2Creates 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 beid , PipCode , customers1 27 A 2 27 C3 29 B4 29 E5 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#4Creates the table #temp_Customers_combined to hold the customers seperated with '/'#5Declares and Sets the loop variablesSET @count_outer = 1SELECT @max_count_outer = (SELECT COUNT(DISTINCT PipCode) FROM #temp_customers)@max_count_outer will hold the number of distinct Productcodes in the table #temp_customersfor our sample data it will be 36The 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 holdPipCode , Customers27 A/C29 B/E30 F#7Finally using the JOIN between tables #temp_Customers_combined & #temp (from #1) you will get the result as:PipCode , Description , MAX(Price) , customers, OrderMonth27 Product1 43 A/C September29 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.ThanksRohit |
|
|
|
|
|
|
|