2017-05-25 78 views
0

我試圖在給定日期之前和之後查找平均分數,其中每個用戶都有自己的日期,我想使用它。在每個行的不同日期之後查找平均值的SQL查詢

我有2個表,第一類包括代理名稱,評分和日期:

Name  Score Date 
----  ----- ---- 
Dan  81  10/1/2016 
Brad  35  8/5/2016 
Allison 92  6/3/2016 
Cindy 95  8/12/2016 
Dan  45  7/16/2016 
Cindy 77  4/16/2016 
Allison 59  3/22/2016 
Brad  55  3/22/2016 

第2表包括代理名稱,他們收到了培訓日期

Agent_name Training_date 
---------- ---------- 
Dan   8/28/2016 
Brad   4/15/2016 
Cindy  3/3/2016 
Allison  5/1/2016 

什麼我期待的是一個輸出,其中包括名稱,訓練日期,訓練前的平均水平和訓練後的平均水平。理想的情況下會是這個樣子

Agent_name Training_date Avg_pre_training Avg_post_training 
---------- ------------- ---------------- ----------------- 
Dan   8/28/2016  45     81 
Brad   4/15/2016  55     35 
Cindy  3/3/2016  0     86 
Allison  5/1/2016  59     92 

我似乎無法得到承認每個人都有自己的時間,我需要考慮的查詢。

+0

如果他們有多個分數會怎麼樣?你只是想包括第一個和最後一個?或者之前和之後立即? –

+0

他們在訓練之前都會有多個分數和多個分數。我希望平均所有之前和平均所有訓練後。 – Boberton

回答

2

下面是BigQuery的標準SQL

#standardSQL 
SELECT 
    Agent_name, Training_date, 
    ROUND(AVG(CASE WHEN date <= Training_date THEN Score END)) AS Avg_pre_training, 
    ROUND(AVG(CASE WHEN date > Training_date THEN Score END)) AS Avg_post_training 
FROM (
    SELECT 
    Agent_name, Score, 
    PARSE_DATE('%m/%d/%Y', date) AS date, 
    PARSE_DATE('%m/%d/%Y', Training_date) AS Training_date 
    FROM training JOIN agents 
    ON Name = Agent_name 
) 
GROUP BY Agent_name, Training_date 
-- ORDER BY Agent_name, Training_date 

您可以使用虛擬數據從你的例子有問題

#standardSQL 
WITH agents AS (
    SELECT 'Dan' AS Name, 81 AS Score, '10/1/2016' AS date UNION ALL 
    SELECT 'Brad', 35, '8/5/2016' UNION ALL 
    SELECT 'Allison', 92, '6/3/2016' UNION ALL 
    SELECT 'Cindy', 95, '8/12/2016' UNION ALL 
    SELECT 'Dan', 45, '7/16/2016' UNION ALL 
    SELECT 'Cindy', 77, '4/16/2016' UNION ALL 
    SELECT 'Allison', 59, '3/22/2016' UNION ALL 
    SELECT 'Brad', 55, '3/22/2016' UNION ALL 
    SELECT 'Allison', 70, '6/25/2016' 
), 
training AS (
    SELECT 'Dan' AS Agent_name, '8/28/2016' AS Training_date UNION ALL 
    SELECT 'Brad', '4/15/2016' UNION ALL 
    SELECT 'Cindy', '3/3/2016' UNION ALL 
    SELECT 'Allison', '5/1/2016' UNION ALL 
    SELECT 'Allison', '6/28/2016' 
) 
SELECT 
    Agent_name, Training_date, 
    ROUND(AVG(CASE WHEN date <= Training_date THEN Score END)) AS Avg_pre_training, 
    ROUND(AVG(CASE WHEN date > Training_date THEN Score END)) AS Avg_post_training 
FROM (
    SELECT 
    Agent_name, Score, 
    PARSE_DATE('%m/%d/%Y', date) AS date, 
    PARSE_DATE('%m/%d/%Y', Training_date) AS Training_date 
    FROM training JOIN agents 
    ON Name = Agent_name 
) 
GROUP BY Agent_name, Training_date 
-- ORDER BY Agent_name, Training_date 

注意此查詢玩:我加了幾行,使例子更通用來解決同一用戶的多種培訓案例

+0

這工作完美。謝謝! – Boberton

0

請參閱下面的答案,使用我控制的前後訓練的where語句,然後將兩個表連接在一起以獲得結果集。

CREATE TABLE #SET1 
(
NAME VARCHAR(20), 
SCORE INT, 
[DATE] DATE 
) 

CREATE TABLE #TRAININGDATE 
(
NAME VARCHAR(20), 
TRAINING_DATE DATE 
) 

INSERT INTO #SET1 
(NAME, SCORE, DATE) 
VALUES 
('Dan',81,'10/1/2016'), 
('Brad',35,'8/5/2016'), 
('Allison',92,'6/3/2016'), 
('Cindy',95,'8/12/2016'), 
('Dan',45,'7/16/2016'), 
('Cindy',77,'4/16/2016'), 
('Allison',59,'3/22/2016'), 
('Brad',55,'3/22/2016') 


INSERT INTO #TRAININGDATE 
VALUES 
('DAN','8/28/2016'), 
('BRAD','4/15/2016'), 
('CINDY','3/3/2016'), 
('ALLISON','5/1/2016') 

SELECT AVG(SCORE) AS AVERAGE_SCORE_BEFORE, A.NAME 
     INTO #TEMP_A 
     FROM #SET1 AS A 
     LEFT JOIN #TRAININGDATE AS B 
     ON A.NAME = B.NAME 
     WHERE DATE < B.TRAINING_DATE 
     GROUP BY A.NAME 


SELECT AVG(SCORE) AS AVERAGE_SCORE_AFTER_TRAINING, A.NAME 
     INTO #TEMP_B 
     FROM #SET1 AS A 
     LEFT JOIN #TRAININGDATE AS B 
     ON A.NAME = B.NAME 
     WHERE DATE > B.TRAINING_DATE 
     GROUP BY A.NAME 

SELECT A.NAME,ISNULL(B.AVERAGE_SCORE_BEFORE,0) AS AVERAGE_PRE_TRAINING,A.AVERAGE_SCORE_AFTER_TRAINING 
     FROM #TEMP_B AS A 
     LEFT JOIN #TEMP_A AS B 
     ON A.NAME = B.NAME 
0

您可以使用派生表來實現:

SELECT T.Agent_Name, T.Training_Date, Avg_Pre_Training, Avg_Post_Training 
FROM Training as T 
JOIN (SELECT T.Agent_Name, AVG(Score) as Avg_Pre_Training 
     FROM Training as T 
     JOIN Scores as S on S.Name= T.Agent_Name 
     WHERE S.Date < T.Training_Date 
     GROUP BY T.Agent_Name 
    ) as Pre on Pre.Agent_Name= T.Agent_Name 
JOIN (SELECT T.Agent_Name, AVG(Score) as Avg_Post_Training 
     FROM Training as T 
     JOIN Scores as S on S.Name= T.Agent_Name 
     WHERE S.Date >= T.Training_Date 
     GROUP BY T.Agent_Name 
    ) as Post on Post.Agent_Name= T.Agent_Name 

不能完全確定我所使用的別名正確的BigQuery的,這是#legacySQL語法,所以它可能需要一些調整。

0

這應該解決Standard SQL

with table1 as(
select 'Dan' as agent_name, 81 as score, '10/1/2016' as date union all 
select 'Brad', 35, '8/5/2016' union all 
select 'Allison', 92, '6/3/2016' union all 
select 'Cindy', 95, '8/12/2016' union all 
select 'Dan', 45, '7/16/2016' union all 
select 'Cindy', 77, '4/16/2016' union all 
select 'Allison', 59, '3/22/2016' union all 
select 'Brad', 55, '3/22/2016'), 

table2 as(
select 'Dan' agent_name, '8/28/2016' as train_date union all 
select 'Brad', '4/15/2016' union all 
select 'Cindy', '3/3/2016' union all 
select 'Allison', '5/1/2016' 
) 

select 
t1.agent_name name, 
t2.train_date train_date, 
avg(case when parse_date("%m/%d/%Y", t2.train_date) >= parse_date("%m/%d/%Y", t1.date) then t1.score end) pre_score, 
avg(case when parse_date("%m/%d/%Y", t2.train_date) < parse_date("%m/%d/%Y", t1.date) then t1.score end) pos_score 
from table1 t1 
join table2 t2 
on t1.agent_name = t2.agent_name 
group by name, train_date 

我們強烈建議您使用此版本中的BigQuery。