SQL 服务器查询同一列的多个条件

SQL Server query for multiple conditions on the same column

这是我正在使用的模式和数据

CREATE TABLE tbl (
    name varchar(20) not null,
    groups int NOT NULL
);

insert into tbl values('a', 35);
insert into tbl values('a', 36);
insert into tbl values('b', 35);
insert into tbl values('c', 36);
insert into tbl values('d', 37);
| name | groups|
|------|-------|
| a    | 35    |
| a    | 36    |
| b    | 35    |
| c    | 36    |
| d    | 37    |

现在我只需要组数大于或等于 35 的名称 但还有一个额外的问题是,当相应的 groups=36 也存在时,我只能包含 group=35 的行

| name | groups|
|------|-------|
| a    | 35    |
| a    | 36    |

第二个条件是它可以包括那些组数大于或等于 36 而组数不等于 35 的名称

| name | groups|
|------|-------|
| c    | 36    |
| d    | 37    |

唯一应该忽略的情况是记录只有 groups=35 而没有对应的 groups=36

| name | groups|
|------|-------|
| b    | 35    |

我试过以下方法

select name from tbl
where groups>=35
group by name
having count(distinct(groups))>=2
or groups>=36;

这是我面临的错误Column 'tbl.groups' is invalid in the HAVING clause because it is not contained in either an aggregate function or the GROUP BY clause.

因此,据我所知,您只想限制组 35 所在的位置。我想,让我们尝试隔离那些只有 groups=35 然后不存在的名称。这是您想要的正确输出吗?

此外,在 where 子句中使用复杂的 OR 通常会导致您的查询不可搜索。最好使用 UNION 或一些构建查询的方法,以便每个部分都可以使用索引(如果可以的话)。

if object_id('tempdb..#tbl') is not null drop table #tbl;
CREATE TABLE #tbl (
    name varchar(20) not null,
    groups int NOT NULL
);

insert into #tbl values('a', 35), ('a', 36), ('b', 35), ('c', 36), ('d', 37);

select * 
from #tbl tbl
WHERE NOT EXISTS
    (
        SELECT COUNT(groups), name 
        FROM #tbl t
        WHERE EXISTS
            (
                SELECT name 
                FROM #tbl tb
                WHERE groups = 35
                and tb.name=t.name
            )
        AND t.name = tbl.name
        GROUP BY name 
        HAVING COUNT(groups)=1
    )
;

您似乎需要一个 exists() 条件。尝试:

select *
from tbl t
where t.groups >= 35
and (
    t.groups > 35
    or exists(select * from tbl t2 where t2.name = t.name and t2.groups = 36)
)

还有其他方法可以安排 where 子句来达到相同的效果。预先设置 t.groups >= 35 条件应该使查询优化器能够利用组上的索引。

您可以为此使用窗口计数

这样可以避免多次加入 table

SELECT
  name,
  groups
FROM (
    SELECT *,
      Count36 = COUNT(CASE WHEN groups = 36 THEN 1 END) OVER (PARTITION BY name)
    FROM tbl
    WHERE groups >= 35
) tbl
WHERE groups >= 36 OR Count36 > 0;

db<>fiddle

试试这个:

DECLARE @tbl table ( [name] varchar(20) not null, groups int NOT NULL );

INSERT INTO @tbl VALUES
    ('a', 35), ('a', 36), ('b', 35), ('c', 36), ('d', 37);

DECLARE @group int = 35;

; WITH cte AS (
    SELECT
        [name]
        , COUNT ( DISTINCT groups ) AS distinct_group_count
    FROM @tbl
    WHERE
        groups >= @group
    GROUP BY
        [name]
)
SELECT t.* FROM @tbl AS t
INNER JOIN cte
    ON t.[name] = cte.[name]
WHERE
    cte.distinct_group_count > 1
    OR t.groups > @group;

RETURNS

+------+--------+
| name | groups |
+------+--------+
| a    |     35 |
| a    |     36 |
| c    |     36 |
| d    |     37 |
+------+--------+

基本上,这会将名称结果限制为值 >= 35 且关联了多个不同组的组,或者组值大于 35 的任何名称。针对您的数据做出了多项假设,但我相信这个逻辑仍然适用。