tags:

views:

67

answers:

1

hello everyone

i have a complex query to be written but cannot figure it out

here are my tables

Sales --one row for each sale made in the system
SaleProducts --one row for each line in the invoice (similar to OrderDetails in NW)
Deals --a list of possible deals/offers that a sale may be entitled to
DealProducts --a list of quantities of products that must be purchased in order to get a deal

now im trying to make a query which will tell me for each sale which deals he may get

the relevant fields are:

Sales: SaleID (PK)
SaleProducts: SaleID (FK), ProductID (FK)
Deals: DealID (PK)
DealProducts: DealID(FK), ProductID(FK), Mandatories (int) for required qty

i believe that i should be able to use some sort of cross join or outer join, but it aint working

here is one sample (of about 30 things i tried)

SELECT  DealProducts.DealID, DealProducts.ProductID, DealProducts.Mandatories, 
        viwSaleProductCount.SaleID, viwSaleProductCount.ProductCount
FROM    DealProducts 
            LEFT OUTER JOIN viwSaleProductCount 
                ON DealProducts.ProductID = viwSaleProductCount.ProductID
GROUP BY DealProducts.DealID, DealProducts.ProductID, DealProducts.Mandatories, 
         viwSaleProductCount.SaleID, viwSaleProductCount.ProductCount

The problem is that it doesn't show any product deals that are not fulfilled (probably because of the ProductID join). i need that also sales that don't have the requirements show up, then I can filter out any SaleID that exists in this query where AmountBought < Mandatories etc

Thank you for your help

+1  A: 

I'm not sure how well I follow your question (where does viwSaleProductCount fit in?) but it sounds like you will want an outer join to a subquery that returns a list of deals along with their associated products. I think it would go something like this:

Select *
From Sales s Inner Join SaleProducts sp on s.SaleID = sp.SaleID
    Left Join (
        Select *
        From Deals d Inner Join DealProducts dp on d.DealID = dp.DealId
    ) as sub on sp.ProductID = sub.ProductID

You may need to add logic to ensure that deals don't appear twice, and of course replace * with the specific column names you'd need in all cases.

edit: if you don't actually need any information from the sale or deal tables, something like this could be used:

Select sp.SaleID, sp.ProductID, sp.ProductCount, dp.DealID, dp.Mandatories
From SaleProducts sp
    Left Join DealProducts as dp on sp.ProductID = dp.ProductID

If you need to do grouping/aggregation on this result you will need to be careful to ensure that deals aren't counted multiple times for a given sale (Count Distinct may be appropriate, depending on your grouping). Because it is a Left Join, you don't need to worry about excluding sales that don't have a match in DealProducts.

AlexCuse
hithanks for answering and so fast!!i believe ur query to be functionally equivalent to SELECT sp.SaleID, sp.ProductID, sp.ProductCount, dp.DealID, dp.ProductID AS Expr1, dp.Mandatories FROM (SELECT SaleID, ProductID, COUNT(SaleProductID) AS ProductCount FROM SaleProducts GROUP BY ProductID, SaleID) AS sp LEFT OUTER JOIN (SELECT DealID, ProductID, Mandatories FROM DealProducts) AS dp ON sp.ProductID = dp.ProductIDill continue in next comment(these r so short)
Yisman
they return same amount of rows. the sales table and deals table dont really have any important info 4 us now. so they can b left out. now this still has a shortcoming. if i have a DealProduct row which has lets say DealID=5,ProductID=7. now if a ceratin Sale (lets say id=1) does not have any SaleProducts with productid=7, then it wont show up in this query, and i would never know that saleid is not eligible to dealid 5
Yisman
If your join is put together properly, then the sales will show and the deal information will be null. Let me see if I can cobble together an updated query based on what it appears you are looking for.
AlexCuse
thanks alex the query u posted, again brings only rows where there is a productcount, meaning at least 1 of this product was in the sale. but in order to figure out eligibility, we need to see also rows where mandatories=3 and productcount = 0. then we can check if all mandatories r met. waiting to c ur new "cobbled" query :-) thanks
Yisman
Well, you said that you don't need anything from the sale table - but it sounds like maybe you do (if you need sales without any products, you sure aren't going to get that from the SaleProducts table). The left join won't exclude anything where there is not a match. Did you add a where clause or anything to the second query I posted above?If not, I think you'll need to post sample data (preferably in the form of a script that can create / populate temp tables) and expected results, because it seems we're experiencing some kind of disconnect.
AlexCuse
hiwhere can i upload the file?btw, just to make sure it runs fine, my scripts, how can i clear the temdb to run and it there (my tempdb has certain similar named tables. thanks)
Yisman
I guess you could drop the tables, but be careful not to drop anything important. Just post what you're working with in terms of create table scripts w/ sample data (inserts) and also your expected result. No need for a file, a few rows should be enough to get the point across.
AlexCuse
hiim sorry i didnt c ur comment earliereven though im set to get notified, im not notified about new commentsi just saw ur comment yesterdayheres the sqll scriptshttp://rapidshare.com/files/401272024/Sales_n_Deals.sql.htmlwaiting for ur excelent advice (btw , i saw ur activity here, very impressive!!!)
Yisman
Can you post your expected results from this data?
AlexCuse
hi im sorry again for not seeing ur comments, i dont know y im not notified...heres the results: SaleID,DealID/4,6/78,5/104,6/150,32/158,32 .i seperated rows with slashes, columns with commasi did this manually (obviously.. :-)) so i hope its accurate, but ideally this is a a list of sales with each deal it is eligible. there may be more then 1 row for each sale, even though currenty there aint. thank u very much again for all ur guidance. i appreciate it very very much. thanks!!!
Yisman
Does the list of deals need to be distinct? Meaning if two products in a sale are both part of the same deal, only one row should be shown? I think that is all that's missing from the query I posted above.
AlexCuse
im not sure i understand the situation, but each deal need only be listed once per sale. does that help? cuz all i need 2 know is if hes eligible or not. i dont care how many times hes esligible. thats waht u mean? can u email me when u answer? as i never know that u comment. im at [email protected] (there r 2 obvious mistakes in the email....) thank u ever so much.
Yisman
also i reran ur query now. it gives me 184 rows. the excpected results i posted has 5 rows. so obviously were far off here.thanks again.
Yisman
You haven't really said what you want to filter on - the query I provided is really only meant to get the data in a form that lets you apply the where clauses you need to get to your result. I'm not entirely sure what these where clauses should be, without knowing it is hard for me to do anything more. I haven't had a ton of time to look at this lately but if you can clarify further I'll try to check back within the week.
AlexCuse
im afraid i dont get u. im trying to filter down the rows to show exactly the results in my comment of july 2. which means to show only those deals that r applicable for the different sales in the db. the way we know if the deal is applicable is by counting the quantiy of the products bought in the sale, and checking that it is equal or greater then the number required in the "mandatories" field in table DealProducts. of course, some deals may have several mandatories (such as must buy 3 milk and 2 cheese to get free pepsi etc...)
Yisman
Ah, that last sentence is what's been missing. In that case you'll need to use a subquery on the left side that returns product ID and count per purchase. Then you'll need to join on left.productid = right.productid and left.count >= right.mandatories to find what deals it is eligible for. Does this make sense? I'll try to find time to get back to this at some point.
AlexCuse