我有两张这样的桌子:
CREATE TABLE XX
(
name VARCHAR(50),
date DATE,
a INT,
b INT,
c INT
);
INSERT INTO XX (name, date, a, b, c)
VALUES
('john', '2010-11-01', 1, 0, 0),
('john', '2010-10-01', 0, 1, 0),
('sara', '1999-02-01', 1, 0, 0),
('julie', '2015-09-01', 1, 0, 0),
('julie', '2015-09-01', 0, 1, 0);
name date a b c
-----------------------
john 2010-11-01 1 0 0
john 2010-10-01 0 1 0
sara 1999-02-01 1 0 0
julie 2015-09-01 1 0 0
julie 2015-09-01 0 1 0
还有另一张桌子
CREATE TABLE YY
(
name VARCHAR(50),
yy_date DATE,
yy CHAR(1)
);
INSERT INTO YY (name, yy_date, yy)
VALUES
('john', '2015-01-01', 'A'),
('john', '2016-01-01', 'A'),
('john', '2000-02-01', 'B'),
('john', '2010-03-01', 'C'),
('julie', '2017-09-01', 'A'),
('julie', '2010-09-01', 'B');
('tom', '2010-09-01', 'B');
name yy_date yy
--------------------
john 2015-01-01 A
john 2016-01-01 A
john 2000-02-01 B
john 2010-03-01 C
julie 2017-09-01 A
julie 2010-09-01 B
tom 2010-09-01 B
我想编写一个 SQL 查询来回答以下问题:
在特定日期收到 type_yy 的客户,即使他们在该日期之前已经拥有相同类型的 xx
例如
最终结果应该是表YY,其中有一个额外的列,指示对于每个(名称,类型),XX是否发生在YY之前或XX是否发生在YY之后。
name yy_date yy xx_vs_yy
--------------------------------------------
john 2015-01-01 A XX happened before YY
john 2016-01-01 A XX happened before YY
john 2000-02-01 B YY happened before XX
john 2010-03-01 C Not applicable
julie 2017-09-01 A XX happened before YY
julie 2010-09-01 B YY happened before XX
tom 2010-09-01 B Not applicable
是否可以使用多个 CTE、CASE WHEN、UNION ALL 和 MAX 语句来执行类似的操作?
WITH earliest_xx AS
(
SELECT name, MIN(date) as earliest_xx_date
FROM XX
GROUP BY name
),
yy_with_xx AS
(
SELECT
y.name,
y.yy_date,
y.yy,
e.earliest_xx_date
FROM YY y
LEFT JOIN earliest_xx e ON y.name = e.name
),
comparison_result AS
(
SELECT
name,
yy_date,
yy,
CASE
WHEN earliest_xx_date IS NULL THEN 'Not applicable'
WHEN earliest_xx_date < yy_date THEN 'XX happened before YY'
ELSE 'YY happened before XX'
END as xx_vs_yy
FROM yy_with_xx
)
SELECT *
FROM comparison_result
ORDER BY name, yy_date;
我对这个问题感到有点迷失......
我认为我在这方面取得了一些进展 - 需要添加一些内容以确保 XX 日期对应于 XX 和 YY 之间的相同类型(例如,a 到 a、b 到 b、c 到 c):
WITH xx_mapped AS (
SELECT name, date,
CASE
WHEN a = 1 THEN 'A'
WHEN b = 1 THEN 'B'
WHEN c = 1 THEN 'C'
END AS xx_type
FROM XX
),
earliest_xx AS (
SELECT name, xx_type, MIN(date) as earliest_xx_date
FROM xx_mapped
GROUP BY name, xx_type
),
yy_with_xx AS (
SELECT
y.name,
y.yy_date,
y.yy,
e.earliest_xx_date
FROM YY y
LEFT JOIN earliest_xx e ON y.name = e.name AND y.yy = e.xx_type
),
comparison_result AS (
SELECT
name,
yy_date,
yy,
CASE
WHEN earliest_xx_date IS NULL THEN 'Not applicable'
WHEN earliest_xx_date < yy_date THEN 'XX happened before YY'
WHEN earliest_xx_date > yy_date THEN 'YY happened before XX'
ELSE 'XX and YY happened on the same date'
END as xx_vs_yy
FROM yy_with_xx
)
SELECT *
FROM comparison_result
ORDER BY name, yy_date;
左连接应该得到你想要的结果:
select y.name, y.yy_date, y.yy,
case when x.date is null then 'Not applicable'
when x.date > y.yy_date then 'YY happened before XX'
else 'XX happened before YY'
end as xx_vs_yy
from yy y
left join xx x on x.name = y.name and (
x.a = 1 and y.yy = 'A' or
x.b = 1 and y.yy = 'B' or
x.c = 1 and y.yy = 'C');
结果:
NAME YY_DATE YY XX_VS_YY
----- ---------- -- ---------------------
john 2015-01-01 A XX happened before YY
john 2016-01-01 A XX happened before YY
john 2000-02-01 B YY happened before XX
john 2010-03-01 C Not applicable
julie 2017-09-01 A XX happened before YY
julie 2010-09-01 B YY happened before XX
tom 2010-09-01 B Not applicable