SQL getting averages with multiple joins

时间:2015-07-31 19:28:19

标签: sql tsql join

I'm trying to write a single query using 3 tables.
The tables and their columns that I will be using are:

Sec – ID, Symbol
Hss – Code, HDate, Holiday
Fddd – ID, Date, Price

Given a symbol AAA, I need to get the ID from the first table and match it with the ID from the third table. The second table's date must match the third table's dates with the condition of Code=1 and Holiday=1.

The Dates in the second and third table are in ascending order with most recent dates at the bottom. I want to get the average 50 day and 200 day prices. The dates in the tables are in ascending order so I want to make it descending and select the top 50 and 200 to get the average prices.

So far I can only get one average. I cannot add a second SELECT TOP 50 or add a subquery within the second avg().

SELECT AVG(TwoHun)TwoHunAvg   --, AVG(Fifty) AS FiftyAvg 
FROM (SELECT TOP 200 Fddd.price AS TwoHun    --, TOP 50 Fddd.price AS Fifty
FROM Sec 
JOIN Fddd
ON Sec.ID = Fddd.ID AND Sec.symbol = 'AAA' 
JOIN Hss 
ON Fddd.date = Hss.Hdate AND Hss.Code = 1 AND Hss.Holiday = 1 
ORDER BY Fddd.Date DESC) AS tmp;

Thanks in advance!

2 个答案:

答案 0 :(得分:0)

I suspect your using SQL Server or MS Access.

One quick solution would be to have your total query as a subquery and then copy a modified version as a second subquery.

Quick rough example:

    SELECT (SELECT
         AVG(Fifty) AS FiftyAvg
       FROM (SELECT TOP 50
         Fddd.price AS Fifty
       FROM Sec
       JOIN Fddd
         ON Sec.ID = Fddd.ID
         AND Sec.symbol = 'AAA'
       JOIN Hss
         ON Fddd.date = Hss.Hdate
         AND Hss.Code = 1
         AND Hss.Holiday = 1
       ORDER BY Fddd.Date DESC) AS tmp)
       AS FiftyAvg,
       (SELECT
         AVG(TwoHun) TwoHunAvg
       FROM (SELECT TOP 200
         Fddd.price AS TwoHun
       FROM Sec
       JOIN Fddd
         ON Sec.ID = Fddd.ID
         AND Sec.symbol = 'AAA'
       JOIN Hss
         ON Fddd.date = Hss.Hdate
         AND Hss.Code = 1
         AND Hss.Holiday = 1
       ORDER BY Fddd.Date DESC) AS tmp)
       AS TwoHundredAverge;

答案 1 :(得分:0)

Consider a union query which even scales for other Averages. I add a Type column to indicate the Averages.

SELECT '200 DAY AVG' As Type, AVG(TwoHun) As Avg
FROM 
  (SELECT TOP 200 Fddd.price AS TwoHun
   FROM Sec 
   INNER JOIN Fddd ON Sec.ID = Fddd.ID 
   INNER JOIN Hss ON Fddd.date = Hss.Hdate
   WHERE Sec.symbol = 'AAA' AND Hss.Code = 1 AND Hss.Holiday = 1 
   ORDER BY Fddd.Date DESC) AS tmp;

UNION

SELECT '50 DAY AVG' As Type, AVG(FiftyHun) As Avg
FROM 
  (SELECT TOP 50 Fddd.price AS FiftyHun
   FROM Sec 
   INNER JOIN Fddd ON Sec.ID = Fddd.ID
   INNER JOIN Hss ON Fddd.date = Hss.Hdate
   WHERE Sec.symbol = 'AAA' AND Hss.Code = 1 AND Hss.Holiday = 1 
   ORDER BY Fddd.Date DESC) AS tmp;

Also, I moved some of your join expressions to where clause which should not change performance but does in readability.