If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

 
Go Back  dBforums > Data Access, Manipulation & Batch Languages > ANSI SQL > minimum price on earliest date

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old 05-17-07, 06:15
aschk aschk is offline
Registered User
 
Join Date: Mar 2007
Location: 636f6d7075746572
Posts: 770
minimum price on earliest date

Ok my first posted question :
(This is related to a travel website)

I have the following table layout :
Code:
CREATE TABLE "public"."package" (
  "id" BIGINT NOT NULL, 
  "accom_code" VARCHAR(4) NOT NULL, 
  "start_date" DATE NOT NULL, 
  "end_date" DATE NOT NULL, 
  "pricing_type" VARCHAR(2), 
  "indic_price" NUMERIC(7,2), 
  "unit_price" NUMERIC(7,2), 
  "adult_age_max_cnt" INTEGER, 
  CONSTRAINT "package_pkey" PRIMARY KEY("id")
) WITH OIDS;
The package table contains a list (a very large one) for holiday accomodation packages.

What i'm trying to get is the following :

The MINIMUM price using the following for "price" :

Code:
CAST (CASE p.pricing_type
             WHEN 'UN' THEN p.unit_price
             WHEN 'PA' THEN p.indic_price*p.adult_age_max_cnt
             ELSE p.unit_price
         END AS NUMERIC(7,2))
AND

The minimum date (i.e. nearest start date) greater than today
WHERE the start_date equals the minimum start_date and the price equals the minimum price.

Any thoughts?

With any luck I will be able to give you an test data insert for this.

This should probably be posted in the POSTGRESQL section however I feel that it is a more general SQL question than anything else.
Reply With Quote
  #2 (permalink)  
Old 05-17-07, 06:20
aschk aschk is offline
Registered User
 
Join Date: Mar 2007
Location: 636f6d7075746572
Posts: 770
What I have thus far :

Code:
SELECT p.accom_code
        ,MIN(CAST (CASE p.pricing_type
             WHEN 'UN' THEN p.unit_price
             WHEN 'PA' THEN p.indic_price*p.adult_age_max_cnt
             ELSE p.indic_price
         END AS NUMERIC(7,2))) as min_price
        ,MIN(p.start_date) as min_start
  FROM package p
      WHERE accom_code IN ('DDNA','ADE9','CGHH','ASEC','BDB9','HGMD','CMEF','BGDE','YRB5','BJAM')
      AND p.duration = 7
      AND start_date > current_date
      AND start_date < current_date + interval '28 day'
      GROUP BY p.accom_code
At the present time i'm getting 10 records (as expected). However I believe these records are WRONG as the minimum price doesn't necessarily match up with the minimum date for a particular (correct me i'm wrong here). How do I go about correcting this?
Reply With Quote
  #3 (permalink)  
Old 05-17-07, 06:29
aschk aschk is offline
Registered User
 
Join Date: Mar 2007
Location: 636f6d7075746572
Posts: 770
Ooh think I nearly got it, can someone verify this :

Code:
SELECT p.accom_code
        ,x.min_start
        ,MIN(CAST (CASE p.pricing_type
             WHEN 'UN' THEN p.unit_price
             WHEN 'PA' THEN p.indic_price*p.adult_age_max_cnt
             ELSE p.indic_price
         END AS NUMERIC(7,2))) as min_price
  FROM package p
  JOIN (
          SELECT p.accom_code,MIN(p.start_date) as min_start
          FROM package p
          WHERE accom_code IN ('DDNA','ADE9','CGHH','ASEC','BDB9','HGMD','CMEF','BGDE','YRB5','BJAM')
          AND p.duration = 7
          AND start_date > current_date
          AND start_date < current_date + interval '28 day'
          GROUP BY p.accom_code
      ) x
  ON p.accom_code = x.accom_code AND x.min_start = p.start_date
      WHERE p.accom_code IN ('DDNA','ADE9','CGHH','ASEC','BDB9','HGMD','CMEF','BGDE','YRB5','BJAM')
      AND p.duration = 7
      AND start_date > current_date
      AND start_date < current_date + interval '28 day'
  GROUP BY p.accom_code,x.min_start
In theory it should give the cheapest price on the earliest start date for each of the 10 accomodation types.

Edit : Just to finish it off I needed the start_date out of it as well (added x.min_start to select and group clause)

Last edited by aschk; 05-17-07 at 06:42.
Reply With Quote
  #4 (permalink)  
Old 05-17-07, 06:36
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,524
looks okay to me

i would not use the same alias "p" in more than one place in the query

and i would probably remove one of the following:
Code:
AND p.duration = 7
AND p.duration = 7
__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
  #5 (permalink)  
Old 05-17-07, 06:41
aschk aschk is offline
Registered User
 
Join Date: Mar 2007
Location: 636f6d7075746572
Posts: 770
LOL oh yeah. I've cleaned it up in the above post now.
However I do have one question to finish it off (and this annoys me about of lot of SQL i've done in the past) :
Is there any way to remove the duplicate WHERE clauses in a query like this, and somehow apply it only once but for both sections? I hope that question makes sense.
Reply With Quote
  #6 (permalink)  
Old 05-17-07, 06:50
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,524
Quote:
Originally Posted by aschk
Is there any way to remove the duplicate WHERE clauses in a query like this
define a view
__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
  #7 (permalink)  
Old 05-17-07, 07:34
stolze stolze is offline
Registered User
 
Join Date: Jan 2007
Location: Jena, Germany
Posts: 2,662
Btw, your queries won't work at all in SQL because you used delimited schema/table/column names in the CREATE TABLE statement (i.e. double-quotes) but not in your query.
__________________
Knut Stolze
IBM DB2 Analytics Accelerator
IBM Germany Research & Development
Reply With Quote
  #8 (permalink)  
Old 05-17-07, 09:06
aschk aschk is offline
Registered User
 
Join Date: Mar 2007
Location: 636f6d7075746572
Posts: 770
That DDL was written in PMS for Postgres so it's a pure copy. I did mention that I was using Postgresql in my first post.

What I DID want to be standard was the SQL query I was doing.
Reply With Quote
  #9 (permalink)  
Old 05-20-07, 09:43
stolze stolze is offline
Registered User
 
Join Date: Jan 2007
Location: Jena, Germany
Posts: 2,662
Well, then you have to use delimited schema/table/column names in your query - as I said.
__________________
Knut Stolze
IBM DB2 Analytics Accelerator
IBM Germany Research & Development
Reply With Quote
  #10 (permalink)  
Old 05-21-07, 06:23
aschk aschk is offline
Registered User
 
Join Date: Mar 2007
Location: 636f6d7075746572
Posts: 770
I have come across a problem with the query above. If two records calculate the same minimum price for one accom_code I can get two results when joined to itself.
i.e. min price and min date is &#163;189 and 25/05/07
when self-joined total price = &#163;567 / 3 adults = &#163;189
and total price = &#163;378 / 2 adults = &#163;189

They both match the minimum price and date and thus both records are output. DOH!

As a quick hack (and I don't like this method) I did a distinct and ordered by total price minimum first.
Reply With Quote
  #11 (permalink)  
Old 07-09-07, 06:22
Peter.Vanroose Peter.Vanroose is offline
Registered User
 
Join Date: Sep 2004
Location: Belgium
Posts: 1,079
Quote:
Originally Posted by aschk
Is there any way to remove the duplicate WHERE clauses in a query like this, and somehow apply it only once but for both sections?
For this purpose, SQL99 defines "common table expressions", i.e., a "WITH" subclause of a select statement. Not yet available in the current version of PostgreSQL but coming soon (8.4 probably)
(DB2, Oracle and SQLServer already have them in place.)
Your query, with CTEs, would become:
Code:
WITH p AS
( SELECT accom_code, start_date,
           MIN(CAST (CASE pricing_type
               WHEN 'UN' THEN unit_price
               WHEN 'PA' THEN indic_price*adult_age_max_cnt
               ELSE indic_price
           END AS NUMERIC(7,2))) as min_price
  FROM   package
  WHERE  accom_code IN ('DDNA','ADE9','CGHH','ASEC',
                        'BDB9','HGMD','CMEF','BGDE','YRB5','BJAM')
    AND  duration = 7
    AND  start_date > current_date
    AND  start_date < current_date + interval '28 day'
),
x AS
( SELECT p.accom_code,MIN(p.start_date) as min_start
  FROM p
  GROUP BY p.accom_code
)
SELECT p.accom_code,x.min_start,p.min_price
  FROM p INNER JOIN x
     ON p.accom_code = x.accom_code AND x.min_start = p.start_date
 GROUP BY p.accom_code,x.min_start
These are effectively "local view definitions", cf suggestion by r937.
(Note that in the above query, the SELECT .. p.min_price is not compatible with the GROUP BY -- maybe add p.min_price to the GROUP BY? Or replace it by "MIN(p.min_price)"?)
__________________
--_Peter Vanroose,
__IBM Certified Database Administrator, DB2 9 for z/OS
__IBM Certified Application Developer
__ABIS Training and Consulting
__http://www.abis.be/

Last edited by Peter.Vanroose; 07-09-07 at 07:53.
Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On