SQL - 当列具有列表中的值和不在同一列表中的值时

时间:2018-02-10 18:49:54

标签: sql postgresql amazon-redshift

不确定说出这个的最好方法,但我正在寻找一种方法来指定列中的值在给定列表中至少有一个值并且不在同一列表中的条件时指定条件,那么列的值应该显示出来。示例表:

email           program
john@john.com   program1
john@john.com   program2
john@john.com   program3
jeff@jeff.com   program3
jeff@jeff.com   program4
steve@steve.com program1
steve@steve.com program2

如果我有这个表和(program1,program2)的列表,我希望显示相应的电子邮件,如果与给定电子邮件关联的程序与给定列表中的至少一个匹配,并且如果给定的电子邮件具有程序不在给定列表中

因此,对于上面的表格和上面给出的列表,我们将使用正确的查询显示:

email
john@john.com

对此的任何帮助将不胜感激。注意:这将在Redshift / PostgreSQL

3 个答案:

答案 0 :(得分:2)

我喜欢使用group byhaving执行此操作。这是一个非常通用的方法:

select email
from t
group by email
having sum( (program = 'program1')::int ) > 0 and
       sum( (program = 'program2')::int ) = 0;

在这种情况下,需要“program1”而不是“program2”。并且,您可以随意添加条件 - 尽可能多。

我忘记了Redshift是否支持::语法。您始终可以使用标准SQL表达:

having sum( case when program = 'program1' then 1 else 0 end ) > 0 and
       sum( case when program = 'program2' then 1 else 0 end ) = 0;

编辑:

我认为@dnswit正确解析OP的问题。逻辑是:

having sum( (program in ('program1', 'program2'))::int ) > 0 and
       sum( (program not in ('program1', 'program2'))::int ) > 0;

答案 1 :(得分:0)

如果您只想要一个电子邮件列表,无论它们在列表中有多少次通过多个程序 它只是library example_lib; import 'package:dson/dson.dart'; part 'main.g.dart'; @serializable class Example extends _$ExampleSerializable { Example() { _callAll(); } fn1() => print('fn1'); fn2() => print('fn2'); fn3() => print('fn3'); fn4() => print('fn4'); _callAll() { reflect(this).methods.forEach((name, method) { if(name != '_callAll') this[name](); }); } } main(List<String> arguments) { _initMirrors(); new Example(); }

答案 2 :(得分:-1)

首先,您的数据表构造错误,您应该使用唯一的标识符,以便检索您指定的程序版本。

所以你的数据库应该是这样的:

> email           program1      program2       program3 
  john@john.com   ProgVersion1  ProgVersion2   ProgVersion3 
  steve@steve.com ProgVersion1  ProgVersion2   ProgVersion3

如果您注意到上表,您现在可以查询以获取指定电子邮件所需的程序值。使用SQL查询,您的表的数据字段是电子邮件,程序1程序2程序3,当检索要显示的字段的值时,您正在使用冗余,您不需要为每个版本的多个版本多次重复电子邮件地址该程序。这不是可预期的方法。

您可以使用的SQL查询:

说明:您将创建一个参数,用作从列表中查询数据表的变量。

> CREATE PROCEDURE spLoadMyProgramVersion
> 
> @email nvarchar(50),
> 
> AS 
>
>BEGIN 
>SELECT program1,program2,program3
>FROM  MyTableName 
>WHERE (email LIKE @email) RETURN

这将允许您通过指定要加载的电子邮件地址在列表中加载所有程序版本,这是一个加载存储过程,只需在创建SQLCommand对象时使用它就可以调用存储过程。 / p>