我有一个简化的表(myPeeps),其中有2列:城市和名称
如果存在以上规则中未提及的其他组合,则必须显示每一行
我该怎么做?我需要额外的加入吗?还是在什么情况下使用情况?
答案 0 :(得分:3)
使用STRING_AGG
:
WITH cte AS (
SELECT city, STRING_AGG(name, ',') WITHIN GROUP(ORDER BY name)AS people
FROM tab
GROUP BY city
)
SELECT *
FROM tab t
WHERE EXISTS (SELECT 1
FROM cte c
WHERE t.city = c.city
AND CASE c.people
WHEN 'John,Mary' THEN 'Mary'
WHEN 'John,Mary,Steve' THEN 'John'
WHEN 'John,Steve' THEN 'Steve'
ELSE t.name
END = t.name)
示例:
+-----+-----------+-------+
| id | city | name |
+-----+-----------+-------+
| 1 | Montreal | John |
| 2 | Montreal | Mary |
| 3 | Berlin | Mary |
| 4 | Berlin | Steve |
| 5 | Berlin | John |
| 6 | Tokyo | Steve |
| 7 | Tokyo | John |
| 8 | Moscow | Mary |
| 9 | Moscow | Steve |
+-----+-----------+-------+
-- Output:
+-----+-----------+-------+
| id | city | name |
+-----+-----------+-------+
| 2 | Montreal | Mary |
| 5 | Berlin | John |
| 6 | Tokyo | Steve |
| 8 | Moscow | Mary |
| 9 | Moscow | Steve |
+-----+-----------+-------+
答案 1 :(得分:0)
这真的很奇怪。我会计算特殊值并使用逻辑:
select t.*
from (select t.*,
sum(case when name = 'John' then 1 else 0 end) over (partition by city) as has_john,
sum(case when name = 'Mary' then 1 else 0 end) over (partition by city) as has_mary,
sum(case when name = 'Steve' then 1 else 0 end) over (partition by city) as has_steve,
sum(case when name not in ('John', 'Mary', 'Steve') then 1 else 0 end) over (partition by city) as has_others
from t
) t
where (name = 'Mary' and has_john = 1 and has_mary = 1 and has_steve = 0 and has_others = 0) or
(name = 'John' and has_john = 1 and has_mary = 1 and has_steve = 1 and has_others = 0) or
(name = 'Steve' and has_john = 1 and has_mary = 0 and has_steve = 1 and has_others = 0) or
(not (has_john = 1 and has_mary = 1 and has_steve = 0 or
has_john = 1 and has_mary = 1 and has_steve = 1 or
has_john = 1 and has_mary = 0 and has_steve = 1
)
);
答案 2 :(得分:0)
对于每一行,如果名称是John,Mary或Steve,则需要弄清楚镇上还有谁,以决定是否将行过滤掉。最自然的方法是对子查询进行左联接。请注意,即使表中除了John,Mary或Steve之外的其他姓名,此解决方案也有效。
WITH cities_with_john AS (SELECT City, Name FROM cities WHERE Name = 'John'),
cities_with_Mary AS (SELECT City, Name FROM cities WHERE Name = 'Mary'),
cities_with_Steve AS (SELECT City, Name FROM cities WHERE Name = 'Steve')
SELECT c.*
FROM cities c
LEFT JOIN cities_with_John j ON c.City = j.City
LEFT JOIN cities_with_Mary m ON c.City = m.City
LEFT JOIN cities_with_Steve s ON c.City = s.City
WHERE c.Name NOT IN ('John', 'Mary', 'Steve') --Anyone else shows up always
OR (c.Name = 'Mary' --Mary only shows up if either John or Steve are not in town
AND (j.Name IS NULL OR s.Name IS NULL))
OR (c.Name = 'Steve' --Steve only shows up if either Mary or Steve are not in town
AND (j.Name IS NULL OR m.Name IS NULL))
OR (c.Name = 'John' --John only shows up if both Mary and Steve are in town, or if both are not
AND ((s.Name IS NULL AND m.Name IS NULL)
OR (s.Name IS NOT NULL AND m.Name IS NOT NULL)))
ORDER BY City, Name
请参阅此数据集的结果,我确定了8个测试用例。在每种情况下,我还为控件添加了第四个名称(凯特):
City Name
----------- ------------
Berlin Kate
Havana John
Havana Kate
Havana Steve
Miami John
Miami Kate
Miami Mary
Miami Steve
Nairobi Kate
Nairobi Mary
New York John
New York Kate
New York Mary
Oslo John
Oslo Kate
Paris Kate
Paris Mary
Paris Steve
Tokio Kate
Tokio Steve
测试用例是:
纽约-约翰和玛丽在市区(应该过滤掉约翰)
迈阿密-所有这些人都在城市中(应该过滤掉史蒂夫和玛丽)
哈瓦那-约翰和史蒂夫在城里(应该过滤掉约翰)
巴黎-玛丽和史蒂夫在城里(应该向所有人展示)
柏林-他们都不在这个城市(应该向所有人展示)
奥斯陆,东京,内罗毕-城市中只有一个(应该向所有人展示)
这是结果:
City Name
------------ ----------
Berlin Kate
Havana Kate
Havana Steve
Miami John
Miami Kate
Nairobi Kate
Nairobi Mary
New York Kate
New York Mary
Oslo John
Oslo Kate
Paris Kate
Paris Mary
Paris Steve
Tokio Kate
Tokio Steve