Я пытаюсь написать эффективный запрос, подобный следующему

«Получить все строки, которые удалены и которые не имеют другой строки с тем же значением, которые не были удалены»

Пример.

| id | val   | deleted | 
========================
| 1  | "foo" |    1
------------------------
| 2  | "bar" |    1
------------------------
| 3  | "foo" |    0
------------------------
| 4  | "baz" |    1
------------------------
| 5  | "qux" |    0
------------------------
| 6  | "baz" |    1
------------------------

======== >

------------------------
| 2  | "bar" |    1
------------------------
| 4  | "baz" |    1
------------------------
| 6  | "baz" |    1
------------------------

Причина, по которой строки с foo отсутствуют в наборе результатов, заключается в том, что одна из них имеет deleted = 0.

0
user7127000 27 Фев 2018 в 07:24

4 ответа

Лучший ответ

Мы можем достичь этого двумя способами.

Ваши данные выглядят так:

SELECT * into #tab FROM(
VALUES(1,'foo',1),
(2,'bar',1),
(3,'foo',0),
(4,'baz',1),
(5,'qux',0),
(6,'baz',1)
) AS A (id,VAL,DELETED)

Способ 1. Использование не существует

select * from #tab t
where DELETED=1 and 
not exists (select * from #tab t1 where t1.DELETED=0 and t1.VAL=t.val)

Способ 2. Использование оператора Apply

SELECT T.* FROM #tab T
OUTER APPLY (SELECT * FROM #tab T1 WHERE T.VAL=T1.VAL AND T1.DELETED=0) as a 
where T.DELETED=1 AND A.id IS NULL
1
Mahesh.K 27 Фев 2018 в 06:28

Чтобы получить только удаленные значения, а не другие, вы можете использовать форму subquery, где подзапрос возвращает только те значения, которые были удалены со значением 1.

SELECT * FROM table 
WHERE val IN (
    SELECT val FROM table
    GROUP BY val
    HAVING COUNT(DISTINCT deleted) = 1 AND
           COUNT(DISTINCT case when deleted = 1 then deleted end) = 1
)

Коррелированный подзапрос может быть полезным

SELECT * FROM table t
    WHERE EXISTS (
        SELECT val FROM table
        WHERE val = t.val
        GROUP BY val
        HAVING COUNT(DISTINCT deleted) = 1 AND
               COUNT(DISTINCT case when deleted = 1 then deleted end) = 1
    )
1
Yogesh Sharma 27 Фев 2018 в 04:48

Если вы любите меня, как присоединиться к пунктам, это вариант:)

declare @t table(id int, val varchar(50) ,deleted bit) 
insert into @t(id,val,deleted)
values 
(1,'foo',1)
,(2,'bar',1)
,(3,'foo',0)
,(4,'baz',1)
,(5,'qux',0)
,(6,'baz',1)

select *
from @t t1
left join(select distinct t2t1.val from @t t2t1 where deleted=0) t2 on t1.val=t2.val
where t2.val is null
0
user3532232 27 Фев 2018 в 06:29

Проверьте этот запрос

select
    a.*
from
    myTable a
where
    not exists (
        select 1
        from mytable b
        where
            a.val = b.val
            and b.deleted = 0
    )

Вот один статья вас может заинтересовать

2
uzi 27 Фев 2018 в 04:29