英文:
Trying to return data into columns from 1st, 2nd, 3rd, 4th (etc.) previous dates
问题
Table 1
+--------+------------+-------+
| URI | Date | Name |
+--------+------------+-------+
| Fred4 | 2023-04-05 | Fred |
| Fred3 | 2023-04-01 | Fred |
| Fred2 | 2023-03-15 | Fred |
| Fred1 | 2023-03-06 | Fred |
| Dave3 | 2023-05-22 | Dave |
| Dave2 | 2023-05-11 | Dave |
| Dave1 | 2023-05-03 | Dave |
| Simon6 | 2023-05-20 | Simon |
| Simon5 | 2023-05-11 | Simon |
| Simon4 | 2023-04-21 | Simon |
| Simon3 | 2023-04-19 | Simon |
| Simon2 | 2023-04-12 | Simon |
| Simon1 | 2023-03-25 | Simon |
+--------+------------+-------+
Table 2
+--------+------------+--------+
| URI | Date | Item |
+--------+------------+--------+
| Fred4 | 2023-04-05 | Top |
| Fred3 | 2023-04-01 | Shorts |
| Fred2 | 2023-03-15 | Band |
| Fred1 | 2023-03-06 | Top |
| Dave3 | 2023-05-22 | Shorts |
| Dave2 | 2023-05-11 | Shoes |
| Dave1 | 2023-05-03 | Top |
| Simon6 | 2023-05-20 | Shorts |
| Simon5 | 2023-05-11 | Band |
| Simon4 | 2023-04-21 | Shorts |
| Simon3 | 2023-04-19 | Top |
| Simon2 | 2023-04-12 | Shoes |
| Simon1 | 2023-03-25 | Shoes |
+--------+------------+--------+
For each URI, I am trying to pull in each previous item so that Item1 = last bought, Item2 = 2nd last bought, etc:
+--------+------------+--------+--------+-------+-------+-------+
| URI | Date | Item1 | Item2 | Item3 | Item4 | Item5 |
+--------+------------+--------+--------+-------+-------+-------+
| Fred4 | 2023-04-05 | Shorts | Band | Top | | |
| Fred3 | 2023-04-01 | Band | Top | | | |
| Fred2 | 2023-03-15 | Top | | | | |
| Fred1 | 2023-03-06 | NULL | | | | |
| Dave3 | 2023-05-22 | Shoes | Top | | | |
| Dave2 | 2023-05-11 | Top | | | | |
| Dave1 | 2023-05-03 | NULL | | | | |
| Simon6 | 2023-05-20 | Band | Shorts | Top | Shoes | Shoes |
| Simon5 | 2023-05-11 | Shorts | Top | Shoes | Shoes | |
| Simon4 | 2023-04-21 | Top | Shoes | Shoes | | |
| Simon3 | 2023-04-19 | Shoes | Shoes | | | |
| Simon2 | 2023-04-12 | Shoes | | | | |
| Simon1 | 2023-03-25 | NULL | | | | |
+--------+------------+--------+--------+-------+-------+-------+
Currently, I can get the most recent last item, but I am struggling with the 2nd, 3rd, etc. despite trying a few different things.
WITH ranked_items AS (
SELECT
t1.URI,
t1.Date,
t1.Name,
t2.Item,
ROW_NUMBER() OVER (PARTITION BY t1.URI ORDER BY t2.Date DESC) AS rn
FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.Name = t2.Name AND t1.Date > t2.Date
)
SELECT
r.URI,
r.Date,
r.Name,
MAX(CASE WHEN r.rn = 1 THEN r.Item ELSE NULL END) AS Item1,
MAX(CASE WHEN r.rn = 2 THEN r.Item ELSE NULL END) AS Item2,
MAX(CASE WHEN r.rn = 3 THEN r.Item ELSE NULL END) AS Item3,
MAX(CASE WHEN r.rn = 4 THEN r.Item ELSE NULL END) AS Item4,
MAX(CASE WHEN r.rn = 5 THEN r.Item ELSE NULL END) AS Item5
FROM ranked_items r
GROUP BY r.URI, r.Date, r.Name
ORDER BY r.URI, r.Date, r.Name;
This SQL query should give you the desired result by using the ROW_NUMBER()
function to rank the items based on the purchase date and then selecting the items for each rank (Item1, Item2, etc.) using conditional aggregation.
英文:
Table 1
+--------+------------+-------+
| URI | Date | Name |
+--------+------------+-------+
| Fred4 | 2023-04-05 | Fred |
| Fred3 | 2023-04-01 | Fred |
| Fred2 | 2023-03-15 | Fred |
| Fred1 | 2023-03-06 | Fred |
| Dave3 | 2023-05-22 | Dave |
| Dave2 | 2023-05-11 | Dave |
| Dave1 | 2023-05-03 | Dave |
| Simon6 | 2023-05-20 | Simon |
| Simon5 | 2023-05-11 | Simon |
| Simon4 | 2023-04-21 | Simon |
| Simon3 | 2023-04-19 | Simon |
| Simon2 | 2023-04-12 | Simon |
| Simon1 | 2023-03-25 | Simon |
+--------+------------+-------+
Table 2
+--------+------------+--------+
| URI | Date | Item |
+--------+------------+--------+
| Fred4 | 2023-04-05 | Top |
| Fred3 | 2023-04-01 | Shorts |
| Fred2 | 2023-03-15 | Band |
| Fred1 | 2023-03-06 | Top |
| Dave3 | 2023-05-22 | Shorts |
| Dave2 | 2023-05-11 | Shoes |
| Dave1 | 2023-05-03 | Top |
| Simon6 | 2023-05-20 | Shorts |
| Simon5 | 2023-05-11 | Band |
| Simon4 | 2023-04-21 | Shorts |
| Simon3 | 2023-04-19 | Top |
| Simon2 | 2023-04-12 | Shoes |
| Simon1 | 2023-03-25 | Shoes |
+--------+------------+--------+
For each URI I am trying to pull in each previous item so that Item1 = last bought, item2 = 2nd last bought etc:
+--------+------------+--------+--------+-------+-------+-------+
| URI | Date | Item1 | Item2 | Item3 | Item4 | Item5 |
+--------+------------+--------+--------+-------+-------+-------+
| Fred4 | 2023-04-05 | Shorts | Band | Top | | |
| Fred3 | 2023-04-01 | Band | Top | | | |
| Fred2 | 2023-03-15 | Top | | | | |
| Fred1 | 2023-03-06 | NULL | | | | |
| Dave3 | 2023-05-22 | Shoes | Top | | | |
| Dave2 | 2023-05-11 | Top | | | | |
| Dave1 | 2023-05-03 | NULL | | | | |
| Simon6 | 2023-05-20 | Band | Shorts | Top | Shoes | Shoes |
| Simon5 | 2023-05-11 | Shorts | Top | Shoes | Shoes | |
| Simon4 | 2023-04-21 | Top | Shoes | Shoes | | |
| Simon3 | 2023-04-19 | Shoes | Shoes | | | |
| Simon2 | 2023-04-12 | Shoes | | | | |
| Simon1 | 2023-03-25 | NULL | | | | |
+--------+------------+--------+--------+-------+-------+-------+
Currently I can get the most recent last item but I am struggling with the 2nd, 3rd etc. despite trying a few different things.
with all_data as (
SELECT t1.URI, t1.date, t1.name
,t2.Item as Item1, t2.Item as Item2, t2.Item as Item3, t2.Item as Item4, t2.Item as Item5
FROM Table1 t1
LEFT OUTER JOIN Table2 t2 on t1.name = t2.name and t1.date > t2.date
)
SELECT URI, date, name, Item1, Item2, Item3, Item4, Item5
from all_data
group by URI, date, name
order by URI, date, name
;
Any help would be great I'm pretty sure the query needs to be quite a lot bigger unless someone knows a few tricks.
Using MySQL and HeidiSQL client.
答案1
得分: 1
以下是翻译好的部分:
with t as (
select t1.uri, t1.date, t1.name, t2.Item,
row_number() over (partition by t1.name order by t2.Date desc ) rn
from Table1 t1 join Table2 t2 on t1.URI = t2.URI and t1.date >= t2.date),
joined as (
select a.uri, a.date, a.name, b.item, b.rn - a.rn rn
from t a left join t b on a.name = b.name and a.rn < b.rn )
select uri, date,
max(case rn when 1 then item end) item1,
max(case rn when 2 then item end) item2,
max(case rn when 3 then item end) item3,
max(case rn when 4 then item end) item4,
max(case rn when 5 then item end) item5
from joined group by uri, date, name order by name, date desc
步骤:
- 对子查询中的行进行编号,
- 基于名称和a.rn < b.rn执行自连接,这会生成包括所需的空行(Simon1,Fred1)的条目,
- 通过减去行号a.rn - b.rn,得到适用于旋转操作的正确值,
- 进行经典的旋转操作,
- 按未显示的列名和日期降序排序行,如果您想这样做。
您在奇怪的旋转类别中获得了奖项;-)
英文:
with t as (
select t1.uri, t1.date, t1.name, t2.Item,
row_number() over (partition by t1.name order by t2.Date desc ) rn
from Table1 t1 join Table2 t2 on t1.URI = t2.URI and t1.date >= t2.date),
joined as (
select a.uri, a.date, a.name, b.item, b.rn - a.rn rn
from t a left join t b on a.name = b.name and a.rn < b.rn )
select uri, date,
max(case rn when 1 then item end) item1,
max(case rn when 2 then item end) item2,
max(case rn when 3 then item end) item3,
max(case rn when 4 then item end) item4,
max(case rn when 5 then item end) item5
from joined group by uri, date, name order by name, date desc
Steps:
- number the rows in the subquery,
- perform a self-join of this subquery based on name and a.rn < b.rn, which multiplies entries including desired empty rows (Simon1, Fred1),
- subtract row numbers a.rn - b.rn, this gives correct value for pivot to operate,
- make classic pivot,
- sort rows by undisplayed column name and date desc, if you want it this way.
You win an award in the category of strange pivots
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论