YelizavetaYR
YelizavetaYR

Reputation: 1711

SQL can't figure out how to join correctly

Having a joining issue

I have one table that has an ID and description column the seasons are new, but the descriptions repeat. so we can have an Adult price for season 34 and an adult price for season 35 etc.

select * from tableA 
-- returns id, description, price, season etc ... 
-- 1 "GT Adult" 10 34
-- 2 "GT Child" 5 34
-- 3 "GT Senior" 8 34 
-- 1 "GT Adult" 11 35
-- 2 "GT Child" 6 35
-- etc. 

TableB has multiple columns these columns have names/headers that correspond to the description column.

select * from tableB 
-- returns customer_no adult, child, senior, order_dt, order_data, season, perf_no etc. 
-- returns 112 0, 12, 2, order_dt, order_data, order_season. 
-- returns 415 23, 0, 0, order_dt, order_data, order_season.

Basically each customer places an order for a given amount of tickets of each type. The information we can use to join is season and performance that they match on ...

but i can't figure out how to say for customer 112 since he got 12 children's tickets he should be charged 5 a ticket, and 2 senior tickets he should be charged 8 dollar for each of those tickets. Where as customer 415 should be charged $10 for each of the 23 tickets. by season.

The only thing I can do for sure is join on season but how do i join on the correct column. Please advise.

Upvotes: 0

Views: 96

Answers (2)

Giorgos Betsos
Giorgos Betsos

Reputation: 72205

You can use PIVOT to get all ticket prices in a single row per season:

SELECT season, [GT Adult], [GT Child], [GT Senior]
FROM (
   SELECT season, price, [description]
   FROM tableA
   ) source
   PIVOT (
      MAX(price)
      FOR [description] IN ([GT Adult], [GT Child], [GT Senior])
   ) pvt

Given the sample data quoted in the OP, the above produces sth like:

season  GT Adult    GT Child    GT Senior
-----------------------------------------
34      10          5           8
35      11          6           NULL

Then you can perform a simple INNER JOIN operation in order to get the total amount per customer order:

SELECT customer_no, adult * [GT Adult] + child *  [GT Child] + senior * [GT Senior] AS total
FROM tableB AS B
INNER JOIN ( 
   SELECT season, [GT Adult], [GT Child], [GT Senior]
   FROM (
      SELECT season, price, [description]
      FROM tableA) source
      PIVOT (
         MAX(price)
         FOR [description] IN ([GT Adult], [GT Child], [GT Senior])
      ) pvt
) t ON b.season = t.season

SQL Fiddle Demo

P.S. The above query works in SQL Server.

EDIT:

To simulate PIVOT in MySQL we have to use conditional aggregates:

select season,
       sum(if(description='GT Adult', price ,null)) as adultPrice,
       sum(if(description='GT Child', price ,null)) as childPrice,
       sum(if(description='GT Senior', price ,null)) as seniorPrice
from tableA 
group by season;

The above query gives us the result set with which a JOIN operation can be performed:

SELECT customer_no, adult * adultPrice + child *  childPrice + senior * seniorPrice AS total
FROM tableB AS b
INNER JOIN ( 
  SELECT season,
       SUM(IF(description='GT Adult', price ,null)) AS adultPrice,
       SUM(IF(description='GT Child', price ,null)) AS childPrice,
       SUM(IF(description='GT Senior', price ,null)) AS seniorPrice
  FROM tableA 
  GROUP BY season) AS a ON b.season = a.season

MySQL Demo here

Upvotes: 0

TonyJenkins
TonyJenkins

Reputation: 35

I don't think you can do what you want with the tables you have. There is no clear way to associate the "adult" column in TableB with the row that contains "GT Adult" in TableA.

You could redesign TableB to solve this:

TableB (customer_no, ticket_type, quantity, order_dt, ...)

So for customer 112 we would have in TableB:

112, "GT_Child", 12 ...
112, "GT_Senior", 2 ...

So you can answer your queries by joining on ticket_type (and possibly other columns if you need them).

If possible, you should move the details of the order itself into a third table (let's call it TableC) and allocate an order number. So we would now have TableA as you have it and then:

TableB (order_no, customer_no, ticket_type, quantity)
TableC (order_no, order_dt, season ...)

Upvotes: 1

Related Questions