SQL: 如何删除由 CASE WHEN 语句创建的重复行
SQL: How to remove duplicate rows created by CASE WHEN statement
我有两个 table:(A) 健身房的顾客和 (B) 餐厅的顾客。我想在 table (A) 中创建一个指示器来指示同一天去过健身房和餐厅的顾客。为此,我使用了以下 SQL 脚本,但它创建了重复的行:
SELECT *,
CASE WHEN a.GymDate = b.RestaurantDate THEN 'Meal + Gym on the same day'
ELSE 'Gym Only' END AS 'Meal+Gym'
FROM Table_A a
LEFT JOIN Table_B b
ON a.customerid = b.customerid;
我可以知道如何只保留 Table_A,但添加 'Meal+Gym' 指标吗?谢谢!
case 表达式不生成行,生成重复行的是您的联接。您可以将日期谓词添加到连接条件,并仅检查记录是否存在,例如
SELECT *,
CASE WHEN b.customerid IS NOT NULL THEN 'Meal + Gym on the same day'
ELSE 'Gym Only'
END AS [Meal+Gym]
FROM Table_A a
LEFT JOIN Table_B b
ON a.customerid = b.customerid
AND a.GymDate = b.RestaurantDate;
如果 table_B 根据 customer/Date 不是唯一的,那么您可能需要做这样的事情来防止重复:
SELECT *,
CASE WHEN r.RestaurantVisit IS NOT NULL THEN 'Meal + Gym on the same day'
ELSE 'Gym Only'
END AS [Meal+Gym]
FROM Table_A a
OUTER APPLY
( SELECT TOP 1 1
FROM Table_B b
WHERE a.customerid = b.customerid
AND a.GymDate = b.RestaurantDate
) AS r (RestaurantVisit);
N.B。虽然使用单引号对列别名有效,但这根本不是一个好习惯,因为它使您的列别名与字符串文字无法区分,而不是从上下文中区分出来。即使您清楚这一点,其他人也可能不清楚,并且由于 reading:writing 代码的比例约为 10:1,因此编写易于阅读的代码很重要。因此,我为您的列名称使用了方括号
我将从 table 位顾客开始,这样您就可以得到既没有去过健身房也没有去过餐厅的顾客的指标。
然后:
select c.*,
(case when exists (select 1
from table_a a join
table_b b
on a.customerid = b.customerid and
a.GymDate = b.RestaurantDate
where a.customerid = c.customerid
)
then 1 else 0
end) as same_day_gym_restaurant_flag
from customers c;
您可以使用 CASE WHEN EXISTS
代替 LEFT JOIN
:
SELECT *,
CASE WHEN EXISTS (
SELECT 1 FROM Table_B b
WHERE a.customerid = b.customerid
AND a.GymDate = b.RestaurantDate)
THEN 'Meal + Gym on the same day'
ELSE 'Gym Only'
END AS 'Meal+Gym'
FROM Table_A a
这假设您不需要结果中 Table_B 的任何数据。
我有两个 table:(A) 健身房的顾客和 (B) 餐厅的顾客。我想在 table (A) 中创建一个指示器来指示同一天去过健身房和餐厅的顾客。为此,我使用了以下 SQL 脚本,但它创建了重复的行:
SELECT *,
CASE WHEN a.GymDate = b.RestaurantDate THEN 'Meal + Gym on the same day'
ELSE 'Gym Only' END AS 'Meal+Gym'
FROM Table_A a
LEFT JOIN Table_B b
ON a.customerid = b.customerid;
我可以知道如何只保留 Table_A,但添加 'Meal+Gym' 指标吗?谢谢!
case 表达式不生成行,生成重复行的是您的联接。您可以将日期谓词添加到连接条件,并仅检查记录是否存在,例如
SELECT *,
CASE WHEN b.customerid IS NOT NULL THEN 'Meal + Gym on the same day'
ELSE 'Gym Only'
END AS [Meal+Gym]
FROM Table_A a
LEFT JOIN Table_B b
ON a.customerid = b.customerid
AND a.GymDate = b.RestaurantDate;
如果 table_B 根据 customer/Date 不是唯一的,那么您可能需要做这样的事情来防止重复:
SELECT *,
CASE WHEN r.RestaurantVisit IS NOT NULL THEN 'Meal + Gym on the same day'
ELSE 'Gym Only'
END AS [Meal+Gym]
FROM Table_A a
OUTER APPLY
( SELECT TOP 1 1
FROM Table_B b
WHERE a.customerid = b.customerid
AND a.GymDate = b.RestaurantDate
) AS r (RestaurantVisit);
N.B。虽然使用单引号对列别名有效,但这根本不是一个好习惯,因为它使您的列别名与字符串文字无法区分,而不是从上下文中区分出来。即使您清楚这一点,其他人也可能不清楚,并且由于 reading:writing 代码的比例约为 10:1,因此编写易于阅读的代码很重要。因此,我为您的列名称使用了方括号
我将从 table 位顾客开始,这样您就可以得到既没有去过健身房也没有去过餐厅的顾客的指标。
然后:
select c.*,
(case when exists (select 1
from table_a a join
table_b b
on a.customerid = b.customerid and
a.GymDate = b.RestaurantDate
where a.customerid = c.customerid
)
then 1 else 0
end) as same_day_gym_restaurant_flag
from customers c;
您可以使用 CASE WHEN EXISTS
代替 LEFT JOIN
:
SELECT *,
CASE WHEN EXISTS (
SELECT 1 FROM Table_B b
WHERE a.customerid = b.customerid
AND a.GymDate = b.RestaurantDate)
THEN 'Meal + Gym on the same day'
ELSE 'Gym Only'
END AS 'Meal+Gym'
FROM Table_A a
这假设您不需要结果中 Table_B 的任何数据。