2008-10-22 6 views
15

Merci à tout le monde pour la réponse de tout le monde. Malheureusement, aucune des solutions ne semble fonctionner de mon côté, et je suppose que l'exemple que j'ai fourni est foiré.SQL: Comment sélectionner uniquement les lignes avec une valeur unique sur certaines colonnes?

Alors laissez-moi essayer à nouveau.

Ma table ressemble à ceci:

contract project activity 
row1 1000 8000 10 
row2 1000 8000 20 
row3 1000 8001 10 
row4 2000 9000 49 
row5 2000 9001 49 
row6 3000 9000 79 
row7 3000 9000 78 

Au fond, la requête que je suis à la recherche retournerait « 2000,49 » pour « contrat, l'activité » parce que le contrat # 2000 a un, et un seul , valeur d'activité unique.

Encore une fois, merci d'un million à l'avance, boroatel

+0

Quel est le PK pour cette table? –

Répondre

13

Mise à jour pour utiliser vos données nouvellement fourni:

Les solutions utilisant les données d'origine se trouvent à la fin de cette réponse.

Utilisation de votre nouvelles données:

DECLARE @T TABLE([contract] INT, project INT, activity INT) 
INSERT INTO @T VALUES(1000, 8000, 10) 
INSERT INTO @T VALUES(1000, 8000, 20) 
INSERT INTO @T VALUES(1000, 8001, 10) 
INSERT INTO @T VALUES(2000, 9000, 49) 
INSERT INTO @T VALUES(2000, 9001, 49) 
INSERT INTO @T VALUES(3000, 9000, 79) 
INSERT INTO @T VALUES(3000, 9000, 78) 

SELECT DISTINCT [contract], activity FROM @T AS A WHERE 
    (SELECT COUNT(DISTINCT activity) 
    FROM @T AS B WHERE B.[contract] = A.[contract]) = 1 

retours: 2000, 49

Solutions utilisant des données originales

AVERTISSEMENT: Les solutions suivantes utilisent les données précédemment données dans la question et peut ne pas avoir de sens pour la question actuelle. Je les ai laissés attachés pour l'exhaustivité seulement.

SELECT Col1, Count(col1) AS count FROM table 
GROUP BY col1 
HAVING count > 1 

Cela devrait vous permettre d'obtenir une liste de toutes les valeurs de col1 qui ne sont pas distinctes. Vous pouvez placer ceci dans une table var ou une table temporaire et vous joindre à elle.

Voici un exemple en utilisant un sous-requête:

DECLARE @t TABLE(col1 VARCHAR(1), col2 VARCHAR(1), col3 VARCHAR(1)) 

INSERT INTO @t VALUES('A', 'B', 'C'); 
INSERT INTO @t VALUES('D', 'E', 'F'); 
INSERT INTO @t VALUES('A', 'J', 'K'); 
INSERT INTO @t VALUES('G', 'H', 'H'); 

SELECT * FROM @t 

SELECT col1, col2 FROM @t WHERE col1 NOT IN 
    (SELECT col1 FROM @t AS t GROUP BY col1 HAVING COUNT(col1) > 1) 

Ce retour:

D E 
G H 

Et une autre méthode que les utilisateurs d'une table temporaire et rejoindre:

DECLARE @t TABLE(col1 VARCHAR(1), col2 VARCHAR(1), col3 VARCHAR(1)) 

INSERT INTO @t VALUES('A', 'B', 'C'); 
INSERT INTO @t VALUES('D', 'E', 'F'); 
INSERT INTO @t VALUES('A', 'J', 'K'); 
INSERT INTO @t VALUES('G', 'H', 'H'); 

SELECT * FROM @t 

DROP TABLE #temp_table 
SELECT col1 INTO #temp_table 
    FROM @t AS t GROUP BY col1 HAVING COUNT(col1) = 1 

SELECT t.col1, t.col2 FROM @t AS t 
    INNER JOIN #temp_table AS tt ON t.col1 = tt.col1 

également retours:

D E 
G H 
+0

Je ne sais pas à quoi ressemblait la question originale lorsque vous avez répondu à cette question, mais compte tenu de ce qui existe actuellement, la cible est manquée et il est extrêmement difficile de la mapper à la cible.Je suppose que c'est parce que vous aviez moins d'informations avec lesquelles travailler que maintenant. –

+1

Oui, le demandeur a changé la question et a utilisé un ensemble de données différent. Les réponses données ci-dessus étaient complètes avec l'ensemble de données donné. J'ai mis à jour la réponse pour refléter cela et ajouté une solution en utilisant le nouvel ensemble de données. – vfilby

7

Pour MySQL:

SELECT contract, activity 
FROM table 
GROUP BY contract 
HAVING COUNT(DISTINCT activity) = 1 
+0

Cela ne fonctionne pas non plus, vous ne pouvez pas avoir des colonnes sur la liste de sélection qui ne sont pas dans le GROUP BY ou un agrégat. Vous devrez utiliser le même principe mais dans une sous-requête ou une jointure. – vfilby

+0

effectivement j'ai testé mon code dans MySQL et cela fonctionne – mrm

+0

* travaillé (avec le premier exemple de données) – mrm

2

modifié!

SELECT distinct contract, activity from @t a 
WHERE (SELECT COUNT(DISTINCT activity) FROM @t b WHERE b.contract = a.contract) = 1 

Et voici un autre - plus court/nettoyant sans sous-requête

select contract, max(activity) from @t 
group by contract 
having count(distinct activity) = 1 
+0

Lorsqu'il est testé dans IBM Informix Dynamic Server 11.50, il ne génère aucune donnée. Le problème est que contrat 2000 a deux lignes de projet avec le même code d'activité, donc COUNT (*) retourne 2, pas 1. –

+0

@Jonathan: la question concerne Microsoft SQL Server, donc l'implémentation de SQL par Informix est complètement hors de propos ici. –

+0

Il est vrai que IDS n'est pas directement pertinent, mais il s'agit d'une implémentation SQL valide et le SQL ci-dessus s'exécute mais ne produit pas la bonne réponse. –

2

Essayez ceci:

select 
     contract, 
     max (activity) 
from 
     mytable 
group by 
     contract 
having 
     count (activity) = 1 
+0

Lors d'un test dans IBM Informix Dynamic Server 11.50, cela ne produit aucune donnée, pas la ligne avec 2000,49 comme requis. Le problème est que contrat 2000 a deux lignes de projet avec le même code d'activité, donc count (activité) = 2 et non 1 comme requis. –

+0

Cela ne fonctionne pas sur SQL Server 2005. Le problème ici est qu'il existe deux lignes pour 2000,49. Vous devez compter seulement des activités distinctes. – vfilby

+0

À la lumière de ces commentaires, voir la réponse de Jetson. –

1

En supposant que votre table de données est appelée ProjetInfo:

SELECT DISTINCT Contract, Activity 
    FROM ProjectInfo 
    WHERE Contract = (SELECT Contract 
          FROM (SELECT DISTINCT Contract, Activity 
            FROM ProjectInfo) AS ContractActivities 
          GROUP BY Contract 
          HAVING COUNT(*) = 1); 

La requête la plus interne identifie Les contrats et les activités. Le niveau suivant de la requête (celui du milieu) identifie les contrats où il n'y a qu'une seule activité. La requête la plus externe extrait ensuite le contrat et l'activité de la table ProjectInfo pour les contrats qui ont une seule activité.

Testé avec IBM Informix Dynamic Server 11.50 - devrait également fonctionner ailleurs.

1

Voici une autre option à l'aide des serveurs sql compte distinct:

DECLARE @T TABLE([contract] INT, project INT, activity INT) 
INSERT INTO @T VALUES(1000, 8000, 10) 
INSERT INTO @T VALUES(1000, 8000, 20) 
INSERT INTO @T VALUES(1000, 8001, 10) 
INSERT INTO @T VALUES(2000, 9000, 49) 
INSERT INTO @T VALUES(2000, 9001, 49) 
INSERT INTO @T VALUES(3000, 9000, 79) 
INSERT INTO @T VALUES(3000, 9000, 78) 



SELECT DISTINCT [contract], activity FROM @T AS A WHERE 
    (SELECT COUNT(DISTINCT activity) 
    FROM @T AS B WHERE B.[contract] = A.[contract]) = 1 
1
SELECT DISTINCT Contract, Activity 
FROM Contract WHERE Contract IN (
SELECT Contract 
FROM Contract 
GROUP BY Contract 
HAVING COUNT(DISTINCT Activity) = 1) 
+0

Testé avec MS SQL 2005 – Hapkido

2

En utilisant la capacité "de table dynamique" dans SQL Server (requêtes sur une requête entourée parenthèse), vous pouvez revenir 2000, 49 w/ce qui suit. Si votre plate-forme n'offre pas un équivalent à l'extension ANSI "table dynamique", vous pouvez toujours utiliser une table temporaire en deux étapes/instruction en insérant les résultats dans la "table dynamique" à une table temporaire, puis effectuer une sélection ultérieure sur la table temporaire.

DECLARE @T TABLE(
    [contract] INT, 
    project INT, 
    activity INT 
) 

INSERT INTO @T VALUES(1000, 8000, 10) 
INSERT INTO @T VALUES(1000, 8000, 20) 
INSERT INTO @T VALUES(1000, 8001, 10) 
INSERT INTO @T VALUES(2000, 9000, 49) 
INSERT INTO @T VALUES(2000, 9001, 49) 
INSERT INTO @T VALUES(3000, 9000, 79) 
INSERT INTO @T VALUES(3000, 9000, 78) 

SELECT 
    [contract], 
    [Activity] = max (activity) 
FROM 
    (
    SELECT 
     [contract], 
     [Activity] 
    FROM 
     @T 
    GROUP BY 
     [contract], 
     [Activity] 
    ) t 
GROUP BY 
    [contract] 
HAVING count (*) = 1 
1

Désolé, vous n'êtes pas en utilisant PostgreSQL ...

SELECT DISTINCT sur le contrat, l'activité * DE theTable ORDER BY contrat, l'activité

http://www.postgresql.org/docs/8.3/static/sql-select.html#SQL-DISTINCT

Oh attendre. Vous ne voulez valeurs avec exactement un ...

contrat SELECT, l'activité, le nombre () DU GROUPE PAR theTable contrat, activité dans un nombre () = 1

3

Je suis un fan de EXISTE PAS

SELECT DISTINCT contract, activity FROM table t1 
WHERE NOT EXISTS (
    SELECT * FROM table t2 
    WHERE t2.contract = t1.contract AND t2.activity != t1.activity 
) 
0

Désolé vieux post, je sais, mais j'eu le même problème, ne pouvait pas être de ce qui précède de travailler pour moi, mais je compris.

Cela a fonctionné pour moi:..

SELECT DISTINCT [colonne] Comme UniqueValues ​​ DE [db] [dbo] [tableau]

0

SELECT DISTINCT Col1, Col2 DE Tableau GROUPE PAR Col1 HAVING COUNT (DISTINCT Col1) = 1

Questions connexes