2017-01-14 8 views
1

мне нужно SELECT *, где отчетливый 'Rua' с различными 'CP' в следующей БД:ВЫБРАТЬ все столбцы из различных двух столбцов

id  Rua     Local   Conc  CP 
81143 dos moinhos   Rio Tinto  Gondomar
81142 dos Moinhos   Rio Tinto  Gondomar 4435 
81141 dos Moinhos   Rio Tinto  Gondomar 4435 

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

SELECT Rua, CP 
FROM Codigo 
GROUP BY Rua, CP 
HAVING COUNT(*) = 1 

Но я хочу все столбцы. SELECT * возвращает «Столбец« Codigo.id »недействителен в списке выбора, потому что он не содержится ни в агрегатной функции, ни в предложении GROUP BY».

Так я пришел на этот ответ: How do I (or can I) SELECT DISTINCT on multiple columns?

я не пошел за принятый ответ, так как я нужен быстрый запрос (это будет использоваться для AJAX предложений поиска). Я использовал другой высокоприоритетный ответ. Таким образом, я создал следующий запрос:

SELECT * From Codigo 
WHERE (Rua,CP) IN (
    SELECT Rua, CP 
    FROM Codigo 
    GROUP BY Rua, CP 
    HAVING COUNT(*) = 1 
); 

Это возвращает выражение не-логического типа, указанный в условиях, когда состояние, как ожидается, около «» ошибки. Почему он ожидает Rua после WHERE быть булевым? В ответе они использовали saleprice, которые не кажутся логическими.

Так что мой вопрос, как я могу выбрать все столбцы включая строк с одинаковым Rua и CP, но те только один раз (DISTINCT)?

ответ

1

SQL-сервер не поддерживает (a,b) in (val1,val2) синтаксиса

Используйте EXISTS, чтобы проверить, что пару

SELECT * 
FROM Codigo C1 
WHERE EXISTS (SELECT 1 
       FROM Codigo C2 
       WHERE C1.Rua = C2.Rua 
         AND C1.CP = C2.CP 
       HAVING Count(*) = 1); 

или использовать COUNT() Over() функцию совокупного окна для подсчета записей для каждого Rua, CP комбинации и фильтровать группу, которая оказывает подсчет как 1, чтобы найти один номер Rua на каждый другой CP.

SELECT * 
FROM (SELECT *, 
       Count(1)OVER(partition BY Rua, CP) AS cnt 
     FROM Codigo C1) A 
WHERE cnt = 1 

Это будет мой предпочтительный подход, так как это намного эффективнее, чем использование EXISTS оптимизатор должен сканировать/искать таблицу только один раз

Если вы не хотите повторяющихся записей используйте ROW_NUMBER()

SELECT * 
FROM (SELECT *, 
       Row_Number()OVER(partition BY Rua, CP Order by id) AS RN 
     FROM Codigo C1) A 
WHERE RN = 1 

Я заказал дубликаты записей с использованием столбца Id и выбрал первую запись из дубликатов.

+0

обе работы , Первое предложение занимает 33 секунды, секунды занимают 3 :) Почему такая разница? – Dillinger

+0

@Dillinger - потому что оптимизатор должен сканировать/искать таблицу только один раз во втором подходе –

+0

Думаю, я не задал вопрос правильно. Я хочу, чтобы строки с такими же «Rua» и «CP» включались, но только один раз. При этом я получаю только те результаты, которые не имеют повторяющихся 'Rua' и' CP'. Если я отредактирую и исправлю свой вопрос, вы исправите свой ответ? – Dillinger

2

с помощью окна функции (одной таблицы чтения):

SELECT t.* 
FROM 
    (SELECT t.*, COUNT(1) OVER (partition BY Rua, CP) AS cnt FROM Codigo t 
) t 
WHERE cnt = 1; 

Использование EXISTS (читает таблицу дважды):

SELECT * 
FROM Codigo t1 
WHERE EXISTS 
    (SELECT 1 
    FROM Codigo t2 
    WHERE t1.Rua = t2.Rua 
    AND t1.CP  = t2.CP 
    GROUP BY Rua, CP 
    HAVING COUNT(*) = 1 
); 

JOIN (дважды еще раз):

SELECT C1.* 
FROM Codigo C1 
INNER JOIN 
    (SELECT Rua, CP FROM Codigo C2 GROUP BY Rua, CP HAVING COUNT(*) = 1 
) C2 
ON C1.Rua = C2.Rua 
AND C1.CP = C2.CP; 
+0

'GROUP BY' в методе' Exists' не требуется –

Смежные вопросы