Получить строки с конкретными дублирующимися значениями SQL - PullRequest
0 голосов
/ 24 января 2019

У меня есть таблица без первичного ключа, которая выглядит следующим образом:

NotId  Status
   1   active
   1   inactive
   2   active
   3   inactive
   4   inactive
   5   active
   5   inactive
   5   extended
   6   inactive
   6   extended

Я хочу получить все NotId s из таблицы.И в случае обнаружения дубликатов NotIds , только с Status active должны быть возвращены.Дубликаты NotIds с другими статусами должны быть пропущены.Если NotIds со статусом Активный отсутствует, то должны быть возвращены все дубликаты.Обратите внимание, что Статус не ограничивается Активным и Неактивным только

Ожидаемый результат:

1   active
2   active
3   inactive
4   inactive
5   active
6   inactive
6   extended

Ответы [ 5 ]

0 голосов
/ 24 января 2019

Я использую group_concat() для разделения идентификаторов, которые содержат 'active' или нет:

select tab.* 
from tab inner join (
  select NotId, concat(',', group_concat(Status), ',') like '%,active,%' active
  from tab
  group by NotId
) t
on t.NotId = tab.NotId
where
  t.active = 0
  or
  (t.active = 1 and tab.Status = 'active')

См. Демоверсию Результаты

| NotId | Status   |
| ----- | -------- |
| 1     | active   |
| 2     | active   |
| 3     | inactive |
| 4     | inactive |
| 5     | active   |
| 6     | inactive |
| 6     | extended |
0 голосов
/ 24 января 2019

Этот запрос удовлетворяет спецификации.(Спецификация может отличаться от спецификации, необходимой для варианта использования, указанного в вопросе.)

SELECT t.notid
     , t.status
  FROM mytable t 
  LEFT
  JOIN ( SELECT b.notid
              , b.status
           FROM mytable b
          WHERE b.status = 'active'
          GROUP
             BY b.notid
       ) n
   ON n.notid = t.notid
WHERE ( n.notid IS NULL OR t.status = 'active' )
ORDER
   BY t.notid
    , t.status

Дано:

INSERT INTO mytable (notid, status) VALUES
 ('1','active')
,('1','inactive')
,('2','active')
,('3','inactive')
,('4','fee')
,('4','fi')
,('4','fo')
,('4','fum')
,('5','active')
,('5','active')
,('5','inactive')
;

Запрос возвращает:

notid  status
-----  ------
1      active
2      active
3      inactive
4      fee
4      fi
4      fo
4      fum
5      active
5      active

В этом запросе предполагается, что notid не равен NULL.Это вернет все строки в таблице, включая дубликаты, за исключением строк со статусом, отличным от «активный», если для данного notid.

существует строка со статусом «активный».
0 голосов
/ 24 января 2019

Возвращает одну строку для каждого NotId.Используйте coalesce в сочетании с case выражениями, чтобы вернуть 'active', если он существует, в противном случае другое значение.

select NotId,
       coalesce(min(case when Status = 'active' then Status end), min(Status)) as Status
from tab
group by NotId
0 голосов
/ 24 января 2019
Решение

jarlh отлично работает, но если вы хотите удалить строки, у которых группа больше 1 и у них нет активности, вам нужно сначала выполнить некоторую работу

SQL DEMO

SELECT `NotId`, CASE WHEN total = 1 
                     THEN result
                     WHEN active > 0 
                     THEN 'active'
                END as `Status`

FROM ( SELECT `NotId`, 
               MAX(`Status`) as result, 
               COUNT(*) as total,  
               COUNT( CASE WHEN `Status` = 'active' THEN 1 END) as active
       FROM Table1
       GROUP BY  `NotId`
  ) as T
WHERE total = 1 or active = 1;
0 голосов
/ 24 января 2019

Используйте группировку с min как

select NotId, min(Status) as Status
  from tab
 where Status in ('active','inactive') 
 group by NotId

Status in ('active','inactive') зависит от комментария

«Повторяющиеся NotIds с другими статусами должны быть пропущены»

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...