SQL Server:当行中存在2个值时选择

SQL Server:当行中存在2个值时选择,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个SQL查询结果 可乐 可乐 A1 C1 A1 C2 A2 C1 A3 C1 A3 C2 你可以做: select col1, col2 from t where col1 in ( select col1 from t where col2 in ('C1', 'C2') group by col1 having count(distinct col2) = 2 ) order by col1, col2 您需要确定哪些按col1分组的行组中同时存在C1和C2-有很多方法

我有一个SQL查询结果

可乐 可乐 A1 C1 A1 C2 A2 C1 A3 C1 A3 C2 你可以做:

select col1, col2 
from t 
where col1 in (
  select col1 from t where col2 in ('C1', 'C2') group by col1 
  having count(distinct col2) = 2
)
order by col1, col2

您需要确定哪些按col1分组的行组中同时存在C1和C2-有很多方法,但有一种方法是按col1分组,分别使用“C1”和“C2”计数,而不是一起使用,因为我假设一个组可能有两个“C1”值和零个“C2”值-然后在有效组中对col1进行内部联接,像这样:

SELECT
    t.*
FROM
    tbl AS t
    INNER JOIN
    (
        SELECT
            col1
        FROM
            tbl
        GROUP BY
            col1
        HAVING
            COUNT( CASE WHEN col2 = 'C1' THEN 1 END ) >= 1
            AND
            COUNT( CASE WHEN col2 = 'C2' THEN 1 END ) >= 1
    ) AS q ON t.col1 = q.col1
更新: OP在下面发布了一条关于此查询的评论回复,并询问如何使用上述技术:

SELECT
    table.col1,
    table2.col2
FROM
    table
    INNER JOIN table2 on table2.col3 = table.col3
WHERE
    table2.col2 = 'C1'
    OR
    table2.col2 = 'C2'
GROUP BY
    table.col1,
    table2.col2
解决方案是使用CTE,因为该查询的结果需要使用两次,因为我们对其本身进行内部联接:

WITH cte AS
(
    -- This is the original query the OP provided in the comment reply. It is unmodified.
    SELECT
        table.col1,
        table2.col2
    FROM
        table
        INNER JOIN table2 on table2.col3 = table.col3
    WHERE
        table2.col2 = 'C1'
        OR
        table2.col2 = 'C2'
    GROUP BY
        table.col1,
        table2.col2
    --
)
SELECT
    t.*
FROM
    cte AS t
    INNER JOIN
    (
        SELECT
            col1
        FROM
            cte
        GROUP BY
            col1
        HAVING
            COUNT( CASE WHEN col2 = 'C1' THEN 1 END ) >= 1
            AND
            COUNT( CASE WHEN col2 = 'C2' THEN 1 END ) >= 1
    ) AS q ON t.col1 = q.col1

如果您使用的是MySQL 8+,有一种方法可以做到这一点:

以cte为例 选择*,MINcol2除以col1 min_col2进行分区, 由col1 max_col2划分的MAXcol2 从你的桌子上 选择col1,col2 来自cte 其中min_col2='C1'和max_col2='C2';
请注意,此答案假设C1和C2是col2仅有的两个可能值。如果可能存在其他值,则上述逻辑必须稍微更改。

您可以使用窗口函数计数,如下所示:

Select col1, col2 from
(Select col1, col2,
       Count(distinct col2) over (partition by col1) as cnt
  From t
 Where col2 in ('C1', 'C2')) t
Where cnt = 2;
Select col1, col2 
  From t
 Where t.col2 in ('C1', 'C2')
   And exists (select 1 from t tt
                Where tt.col1 = t.col1
                  And tt.col2 in ('C1', 'C2')
                  And t.col2 <> tt.col2)
您还可以按如下方式使用exists:

Select col1, col2 from
(Select col1, col2,
       Count(distinct col2) over (partition by col1) as cnt
  From t
 Where col2 in ('C1', 'C2')) t
Where cnt = 2;
Select col1, col2 
  From t
 Where t.col2 in ('C1', 'C2')
   And exists (select 1 from t tt
                Where tt.col1 = t.col1
                  And tt.col2 in ('C1', 'C2')
                  And t.col2 <> tt.col2)

如果没有重复行,我建议使用窗口函数:

select col1, col2
from (select t.*,
             sum(case when col2 in ('C1', 'C2') then 1 else 0 end) over (partition by col1) as cnt
     from t
    ) t
Where cnt = 2;
注意:即使col2的值不是上面提到的两个值,这也可以工作。在这种情况下,它返回所有行

这就是我对这个问题的解释

您还可以使用where子句中的子查询来表达这一点。存在一种使用的方法:

这将适用于重复项以及其他列。我更喜欢存在,但您也可以将其表示为:

select col1, col2
from t t1
where (select count(distinct t2.col2)
       from t t2
       where t2.col1 = t1.col1 and
             t2.col2 in ('C1', 'C2')
      ) = 2;
      

如果有一个C3值,你会期望它也被返回吗?A2是out,因为它只有C1。你能在“C1”、“C2”和having中尝试像col2这样的in运算符吗clause@Ajay2707这仅适用于您希望查看单行,而OP希望计算行组。如果一个组有两个C1值而没有C2值,则这不起作用。@Dai Yes,但是你提到的案例根据问题是无效的。OP没有说col2值保证是不同的。你在哪里看到的?@TimBiegeleisen是的,好多了。对不起。固定的现在让OP对我们的答案发表评论。从table2.col3=table.col3的表内部联接table2中选择table.col1,table2.col2,其中table2.col2='C1'或table2.col2='C2'按table.col1,table2.col2分组,如果存在某种级别的内部联接表,如何实现?@UqubeSdnBhd我不理解你的问题,你说的某种级别的内部联接表是什么意思?。此外,你在评论中发布的SQL不正确-我不知道你为什么发布它。如何在我在上一个评论中发布的SQL中使用你的方法。@UqubeSdnBhd我已更新了我的答案。