同じIDであるがnullの行を選択し、そのIDの別の列で他の値を選択する


9

特定のユーザー名列NULL以外の値とその他の値を持つ行のみを取得したいNULL

その特定のユーザー名に対して両方の行にnullがあるか、両方にnull以外の値がある場合、出力に表示されません。nullと他の値を持つ同じユーザー名の行が3つ以上ある場合は、それらが表示されます。

以下はサンプルのサンプルと出力です。SQLクエリを使用してどのように実行できますか?

+----------+-------+
| username | col2  |
+----------+-------+
| a        | abc   |
| a        | ef    |
| b        | null  |
| b        | null  |
| c        | der   |
| c        | null  |
+----------+-------+

出力

+----------+------+
| username | col2 |
+----------+------+
| c        | der  |
| c        | null |
+----------+------+

1
2行あり、2行ありの場合はどうd, derなりd, nullますか?
ypercubeᵀᴹ

1
@ypercube次に、dの4行すべてが表示されます
IT研究者

1
で行がありe, one、?でe, two2 行以上ある場合 e, null
ypercubeᵀᴹ

1
@ypercubeすると、すべての行が表示されます。
IT研究者

回答:


12

あなたは内の値の両方でユーザ名を取得するには、条件付き集約を使用することができるはずcol2などnull

条件でHAVING句を使用することをお勧めします。クエリは次のようになります。

select username
from yourtable
group by username
having sum(case when col2 is not null then 1 else 0 end) = 1
  and sum(case when col2 is null then 1 else 0 end) = 1

SQL Fiddle with Demoを参照してください。このクエリは、データをユーザー名ごとにグループ化し、条件ロジックを使用してがnullでない場合とnullの場合のcol2両方の条件を満たすかどうかを確認します。col2 col2

次に、これをサブクエリなどで使用して、usernameおよびcol2値を取得できます。

select 
  t.username, 
  t.col2
from yourtable t
inner join
(
  select username
  from yourtable
  group by username
  having sum(case when col2 is not null then 1 else 0 end) = 1
    and sum(case when col2 is null then 1 else 0 end) = 1
) d
  on t.username = d.username

SQL Fiddle with Demoを参照してください。

col2両方nullと別の値を持つ複数の行がある場合は、HAVING句をわずかに変更する必要があります。

select 
  t.username, 
  t.col2
from yourtable t
inner join
(
  select username
  from yourtable
  group by username
  having sum(case when col2 is not null then 1 else 0 end) >= 1
    and sum(case when col2 is null then 1 else 0 end) >= 1
) d
  on t.username = d.username;

SQL Fiddle with Demoを見る


あなたのクエリは1点を逃しました(実際には私も問題について明確に述べていません)。nullと他の値を持つ同じユーザー名の行が3つ以上ある場合は、それらが表示されます。クエリではそれらは来ません(たとえば、ユーザー名「c」とnullまたは何らかの値を持つ別の行がある場合、そのフィドルで
IT研究者

1
あなたが変更する必要がある-簡単な修正である@ITresearcher HAVINGなるように句を>=1- sqlfiddle.com/#!3/8af72/2
タリン

わかりました。JGAによる回答も機能します。
IT研究者

8

別の解決策:

SELECT Y1.*
FROM dbo.yourtable AS Y1
WHERE Y1.username = ANY
(
    SELECT Y2.username 
    FROM dbo.yourtable AS Y2
    WHERE Y2.col2 IS NULL
    INTERSECT
    SELECT Y3.username 
    FROM dbo.yourtable AS Y3
    WHERE Y3.col2 IS NOT NULL
);

実行計画

同様の論理的な流れで:

SELECT Y.* 
FROM dbo.yourtable AS Y
WHERE EXISTS
    (
    SELECT * 
    FROM dbo.yourtable AS Y2 
    WHERE Y2.username = Y.username 
    AND Y2.col2 IS NULL
    )
AND EXISTS
    (
    SELECT * 
    FROM dbo.yourtable AS Y3 
    WHERE Y3.username = Y.username 
    AND Y3.col2 IS NOT NULL
    );

実行計画

さらに別の:

SELECT
    SQ1.username,
    SQ1.col2
FROM 
(
    SELECT
        Y.username, 
        Y.col2,
        MinCol2 = 
            MIN(CASE WHEN Y.col2 IS NULL THEN -1 ELSE 1 END) 
            OVER (PARTITION BY Y.username), 
        MaxCol2 = 
            MAX(CASE WHEN Y.col2 IS NULL THEN -1 ELSE 1 END) 
            OVER (PARTITION BY Y.username)
    FROM dbo.yourtable AS Y
) AS SQ1
WHERE 
    SQ1.MinCol2 = -SQ1.MaxCol2;

実行計画


いい答えだ。私のテーブルは巨大でした。
IT研究者、

5

それを行うちょうど別の方法:

; WITH cte AS
  ( SELECT username, col2,
           cnt_all  = COUNT(*) OVER (PARTITION BY username),
           not_null = COUNT(col2) OVER (PARTITION BY username)
    FROM yourtable AS a
  )
SELECT username, col2
FROM cte
WHERE cnt_all > not_null 
  AND not_null > 0 ;

4

これも機能します。 SQL Fiddleデモ

各ユーザー名の合計行としてC1、各ユーザー名の合計null行としてC2を取得し、これらの値を後で比較します。

SELECT username, col2 FROM
(
SELECT *,
(SELECT Count(*) FROM T Where username = T1.username) C1,
(SELECT Count(*) FROM T Where username = T1.username and col2 is null) C2
FROM T T1
) T2
WHERE C2 > 0 And C1 <> C2

3

サブクエリを使用して、次のようなユーザー名を選択します。

select username
from   dbo.yourtable
group by username
having sum(distinct case when col2 is not null then 1 else 2 end) = 3;

-1

これを試してみました...

select a.username from  
(select username ,col2 
   from yourtable
where col2 is null) a,(select username ,col2 
                       from yourtable
                        where col2 is not null) b
where a.username=b.username;

2
これにより、クロス結合が発生します。ユーザー名の場合、col2がnullの行が3行、col2がnullでない行が2行ある場合、最終結果は5ではなく6行にcol2なり、出力には含まれません。
ypercubeᵀᴹ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.