SQL для проверки, когда пары не совпадают

Я использую SQL Server 2012. У меня есть следующие образцы данных.

Date        Type    Symbol      Price
6/30/1995   gaus    313586U72   109.25
6/30/1995   gbus    313586U72   108.94
6/30/1995   csus    NES         34.5
6/30/1995   lcus    NES         34.5
6/30/1995   lcus    NYN         40.25
6/30/1995   uaus    NYN         40.25
6/30/1995   agus    SRR         10.25
6/30/1995   lcus    SRR         0.45
7/1/1995    gaus    313586U72   109.25
7/1/1995    gbus    313586U72   108.94

Я хочу отфильтровать совпадение символа и цены. Это нормально, если тип не совпадает. Таким образом, с приведенными выше данными я ожидаю увидеть только

Date        Type    Symbol      Price
6/30/1995   gaus    313586U72   109.25
6/30/1995   gbus    313586U72   108.94
6/30/1995   agus    SRR         10.25
6/30/1995   lcus    SRR         0.45
7/1/1995    gaus    313586U72   109.25
7/1/1995    gbus    313586U72   108.94

NES и NYN были отфильтрованы, потому что их символ и цена совпадают.

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

* **ОБНОВЛЕНИЕ Я буду проверять ответы. Я должен был упомянуть, что просто хочу видеть дубликаты для символа и цены, которые происходят в одну и ту же дату. Также стол называется duppri


person Jay C    schedule 03.07.2015    source источник
comment
Я только что заметил ваше редактирование; чтобы искать дубликаты в ту же дату, вы можете добавить еще одно условие к моим ответам, см. это: sqlfiddle.com/#!6/29d67/1   -  person jpw    schedule 03.07.2015
comment
@jpw Я заставил ваш исходный запрос работать, добавив строку даты, как вы указали. Один вопрос, что делает часть запроса select 1?   -  person Jay C    schedule 03.07.2015
comment
Когда вы используете exists, интересует только то, возвращает ли запрос что-то, а не то, что он возвращает. Использование select 1 — это просто способ указать, что столбцы не важны, плюс это делает запрос короче.   -  person jpw    schedule 03.07.2015


Ответы (3)


Один из способов — использовать предикат exists с коррелированным подзапросом, который проверяет, что конкретный символ имеет более одной цены:

select * from table1 t
where exists (
  select 1
  from table1
  where symbol = t.symbol
  and price <> t.price);

Пример скрипта SQL

Это вернет:

|                   Date | Type |    Symbol |  Price |
|------------------------|------|-----------|--------|
| June, 30 1995 02:00:00 | gaus | 313586U72 | 109.25 |
| June, 30 1995 02:00:00 | gbus | 313586U72 | 108.94 |
| June, 30 1995 02:00:00 | agus |       SRR |  10.25 |
| June, 30 1995 02:00:00 | lcus |       SRR |   0.45 |
| July, 01 1995 02:00:00 | gaus | 313586U72 | 109.25 |
| July, 01 1995 02:00:00 | gbus | 313586U72 | 108.94 |

Редактировать: вдохновленный умным ответом Гордона Линоффа, другим вариантом может быть использование avg() в качестве оконной функции:

select Date, Type, Symbol, Price  
from (
  select Date, Type, Symbol, Price, avg = avg(price) over (partition by symbol) 
  from table1) a
where avg <> price;

Изменить: с проверкой, чтобы гарантировать, что возвращаются только дубликаты одной и той же даты: http://www.sqlfiddle.com/#!6/29d67/1

person jpw    schedule 03.07.2015
comment
Проголосуйте за оконную функцию. Но как насчет использования count distinct в качестве оконной функции? - person SQL Police; 03.07.2015
comment
Это было бы еще проще. - person SQL Police; 03.07.2015
comment
... Я только что попробовал, а также сейчас прочитал, что distinct не поддерживается с partition by. (только count, без distinct). Но, возможно, это будет будущая функция SQL Server. За это уже есть голоса пользователей. - person SQL Police; 03.07.2015
comment
Да, но на самом деле это часть стандарта ANSI. SQL Server просто не реализовал все из стандарта. Кстати, в Oracle это возможно. - person SQL Police; 03.07.2015

Я бы подошел к этому, используя оконные функции:

select s.*
from (select s.*,
             min(price) over (partition by symbol) as minprice,
             max(price) over (partition by symbol) as maxprice
      from sample s
     ) s
where minprice <> maxprice;
person Gordon Linoff    schedule 03.07.2015
comment
Разве нельзя было бы использовать count distinct в качестве оконной функции вместо использования min и max ? [Примечание: Голосуйте за. Должно быть гораздо больше использования оконных функций] - person SQL Police; 03.07.2015
comment
Рег. count distinct: Я только что обнаружил, что distinct не поддерживается с partition by. (только count). Возможно, это будет будущая функция SQL Server. Голоса пользователей уже есть. - person SQL Police; 03.07.2015

Используйте дополнительный выбор с GROUP BY в сочетании с HAVING COUNT DISTINCT, чтобы найти «плохие» символы:

select * from your_table
where symbol not in
(
  select symbol
  from your_table
  group by symbol
  having count(distinct price) > 1
)
person jarlh    schedule 03.07.2015