显示 SQL 行到行数可能不同的列
Displaying SQL rows to columns where the row count may vary
我有一个 main table 如下
ID Latest_rating
--- --------------
1 3
2 5
然后我有一个 main_audit table 显示评级变化历史如下
ID rating rating_change_date
-- ------ ------------------
1 2 26-Sep-15
1 4 16-Apr-14
1 3 10-Mar-13
2 3 04-Apr-15
2 2 01-Oct-13
所以我必须同时加入 tables 并且应该显示如下
ID Latest_Rating 1st_Rating rating_change_date 2nd_rating rating_change_date
-- ------------- ---------- ------------------ ---------- ------------------
1 3 3 10-Mar-13 4 16-Apr-14
2 5 2 01-Oct-13 3 04-Apr-15
我应该在上面的列中显示为 1st rating, 2nd rating, 3rd rating, 4 rating
您可以使用 row_number()
和聚合来做到这一点。棘手的部分是:
select ma.id,
max(case when seqnum = 1 then rating end) as first_rating,
max(case when seqnum = 1 then rating_change_date end) as first_rating_change_date,
max(case when seqnum = 2 then ma.rating end) as second_rating,
max(case when seqnum = 2 then ma.rating_change_date end) as second_rating_change_date
from (select ma.*,
row_number() over (partition by id order by rating_change_date desc) as seqnum
from main_audit ma
) ma
group by id;
然后您可以组合它们:
with ma as (
select ma.id,
max(case when seqnum = 1 then rating end) as first_rating,
max(case when seqnum = 1 then rating_change_date end) as first_rating_change_date,
max(case when seqnum = 2 then ma.rating end) as second_rating,
max(case when seqnum = 2 then ma.rating_change_date end) as second_rating_change_date
from (select ma.*,
row_number() over (partition by id order by rating_change_date desc) as seqnum
from main_audit ma
) ma
group by id
)
select m.id, m.latest_rating,
ma.first_rating, ma.first_rating_change_date,
ma.second_rating, ma.second_rating_change_date
from main m join
ma
on m.id = ma.id;
根据您的评论,如果评级相同,您可以合并,如果有 3 次更改 1 和 2 相同,则可以采用这种方式的最短日期 1 和 2 合并,第三次更改上升到第 2 位. 也不需要 3 个查询,你可以在 1 个嵌套的 select 中使用连接和条件聚合来完成:
SELECT
m.Id
,m.Latest_rating
,MAX(CASE WHEN t.RateChangeNum = 1 THEN t.rating END) as first_rating
,MAX(CASE WHEN t.RateChangeNum = 1 THEN t.MinRatingChangeDate END) as first_rating_change_date
,MAX(CASE WHEN t.RateChangeNum = 2 THEN t.rating END) as first_rating
,MAX(CASE WHEN t.RateChangeNum = 2 THEN t.MinRatingChangeDate END) as first_rating_change_date
FROM
main m
INNER JOIN
(
SELECT
ID
,rating
,MIN(rating_change_date) as MinRatingChangeDate
,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY MIN(rating_change_date)) as RateChangeNum
FROM
main_audit a
GROUP BY
ID
,rating
) t
ON m.Id = t.ID
GROUP BY
m.Id
,m.Latest_rating
至于您对变化数量的评论。您可以硬编码到您认为可能存在或可能不存在的完整数字,如果没有那么多更改,或者您需要转向动态 sql.
,则字段将为空
条件聚合而不是 PIVOT 的原因是因为你需要聚合多个列,如果你只想要评级或日期那么你可以使用 PIVOT 并且会少一些代码编写(http://www.oracle.com/technetwork/articles/sql/11g-pivot-097235.html)
我有一个 main table 如下
ID Latest_rating
--- --------------
1 3
2 5
然后我有一个 main_audit table 显示评级变化历史如下
ID rating rating_change_date
-- ------ ------------------
1 2 26-Sep-15
1 4 16-Apr-14
1 3 10-Mar-13
2 3 04-Apr-15
2 2 01-Oct-13
所以我必须同时加入 tables 并且应该显示如下
ID Latest_Rating 1st_Rating rating_change_date 2nd_rating rating_change_date
-- ------------- ---------- ------------------ ---------- ------------------
1 3 3 10-Mar-13 4 16-Apr-14
2 5 2 01-Oct-13 3 04-Apr-15
我应该在上面的列中显示为 1st rating, 2nd rating, 3rd rating, 4 rating
您可以使用 row_number()
和聚合来做到这一点。棘手的部分是:
select ma.id,
max(case when seqnum = 1 then rating end) as first_rating,
max(case when seqnum = 1 then rating_change_date end) as first_rating_change_date,
max(case when seqnum = 2 then ma.rating end) as second_rating,
max(case when seqnum = 2 then ma.rating_change_date end) as second_rating_change_date
from (select ma.*,
row_number() over (partition by id order by rating_change_date desc) as seqnum
from main_audit ma
) ma
group by id;
然后您可以组合它们:
with ma as (
select ma.id,
max(case when seqnum = 1 then rating end) as first_rating,
max(case when seqnum = 1 then rating_change_date end) as first_rating_change_date,
max(case when seqnum = 2 then ma.rating end) as second_rating,
max(case when seqnum = 2 then ma.rating_change_date end) as second_rating_change_date
from (select ma.*,
row_number() over (partition by id order by rating_change_date desc) as seqnum
from main_audit ma
) ma
group by id
)
select m.id, m.latest_rating,
ma.first_rating, ma.first_rating_change_date,
ma.second_rating, ma.second_rating_change_date
from main m join
ma
on m.id = ma.id;
根据您的评论,如果评级相同,您可以合并,如果有 3 次更改 1 和 2 相同,则可以采用这种方式的最短日期 1 和 2 合并,第三次更改上升到第 2 位. 也不需要 3 个查询,你可以在 1 个嵌套的 select 中使用连接和条件聚合来完成:
SELECT
m.Id
,m.Latest_rating
,MAX(CASE WHEN t.RateChangeNum = 1 THEN t.rating END) as first_rating
,MAX(CASE WHEN t.RateChangeNum = 1 THEN t.MinRatingChangeDate END) as first_rating_change_date
,MAX(CASE WHEN t.RateChangeNum = 2 THEN t.rating END) as first_rating
,MAX(CASE WHEN t.RateChangeNum = 2 THEN t.MinRatingChangeDate END) as first_rating_change_date
FROM
main m
INNER JOIN
(
SELECT
ID
,rating
,MIN(rating_change_date) as MinRatingChangeDate
,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY MIN(rating_change_date)) as RateChangeNum
FROM
main_audit a
GROUP BY
ID
,rating
) t
ON m.Id = t.ID
GROUP BY
m.Id
,m.Latest_rating
至于您对变化数量的评论。您可以硬编码到您认为可能存在或可能不存在的完整数字,如果没有那么多更改,或者您需要转向动态 sql.
,则字段将为空条件聚合而不是 PIVOT 的原因是因为你需要聚合多个列,如果你只想要评级或日期那么你可以使用 PIVOT 并且会少一些代码编写(http://www.oracle.com/technetwork/articles/sql/11g-pivot-097235.html)