Question

J'ai besoin de récupérer toutes les lignes d'une table où les 2 colonnes sont toutes différentes.Donc, je veux que toutes les ventes qui n'ont pas d'autres ventes qui s'est passé le même jour pour le même prix.Les ventes qui sont uniques en fonction du jour et le prix sera mis à jour à un état actif.

Donc, je suis en train de penser:

UPDATE sales
SET status = 'ACTIVE'
WHERE id IN (SELECT DISTINCT (saleprice, saledate), id, count(id)
             FROM sales
             HAVING count = 1)

Mais mon cerveau fait mal d'aller encore plus loin.

Était-ce utile?

La solution

SELECT DISTINCT a,b,c FROM t

est environ l'équivalent de:

SELECT a,b,c FROM t GROUP BY a,b,c

C'est une bonne idée d'obtenir utilisé pour le GROUPE PAR la syntaxe, car il est plus puissant.

Pour votre requête, je ferais comme ceci:

UPDATE sales
SET status='ACTIVE'
WHERE id IN
(
    SELECT id
    FROM sales S
    INNER JOIN
    (
        SELECT saleprice, saledate
        FROM sales
        GROUP BY saleprice, saledate
        HAVING COUNT(*) = 1 
    ) T
    ON S.saleprice=T.saleprice AND s.saledate=T.saledate
 )

Autres conseils

Si vous mettez ensemble les réponses jusqu'à présent, les nettoyer et de les améliorer, vous arrivez à ce supérieur de la requête:

UPDATE sales
SET    status = 'ACTIVE'
WHERE  (saleprice, saledate) IN (
    SELECT saleprice, saledate
    FROM   sales
    GROUP  BY saleprice, saledate
    HAVING count(*) = 1 
    );

Qui est beaucoup plus rapide que l'un d'eux.Les armes nucléaires de la performance de la actuellement accepté de répondre par un facteur de 10 - 15 (dans mes tests sur PostgreSQL 8.4 9.1).

Mais cela est encore loin d'être optimale.L'utilisation d'un NOT EXISTS (anti-)semi-jointure pour des performances encore meilleures. EXISTS est SQL standard, a été autour pour toujours (au moins depuis PostgreSQL 7.2, longtemps avant que cette question a été posée) et l'adapte les exigences parfaitement:

UPDATE sales s
SET    status = 'ACTIVE'
WHERE  NOT EXISTS (
   SELECT FROM sales s1                     -- SELECT list can be empty for EXISTS
   WHERE  s.saleprice = s1.saleprice
   AND    s.saledate  = s1.saledate
   AND    s.id <> s1.id                     -- except for row itself
   )
AND    s.status IS DISTINCT FROM 'ACTIVE';  -- avoid empty updates. see below

db<>violon ici
Ancien SQL Violon

Clé Unique pour identifier la ligne

Si vous n'avez pas une clé primaire ou unique pour la table (id dans l'exemple), vous pouvez le remplacer par le système de colonne ctid aux fins de la présente requête (mais pas pour d'autres fins):

   AND    s1.ctid <> s.ctid

Chaque table doit avoir une clé primaire.Ajoutez-en un si vous n'avez pas, encore.Je vous propose un serial ou un IDENTITY colonne dans Postgres 10+.

Connexes:

Comment est-ce plus rapide?

La sous-requête dans la EXISTS anti-semi-jointure peut arrêter l'évaluation dès la première dupe est trouvé (pas de point en regardant de plus).Pour une table de base avec quelques doublons, ce n'est que légèrement plus efficace.Avec beaucoup de doublons cela devient façon plus efficace.

Exclure vide mises à jour

Pour les lignes qui ont déjà status = 'ACTIVE' cette mise à jour ne change rien, mais encore l'insertion d'une nouvelle version de ligne à coût complet (quelques exceptions s'appliquent).Normalement, vous ne voulez pas cela.Ajouter un autre WHERE condition comme démontré ci-dessus pour éviter cela et le rendre encore plus rapide:

Si status est défini NOT NULL, vous pouvez simplifier à:

AND status <> 'ACTIVE';

Différence subtile dans la gestion des valeurs NULL

Cette requête (contrairement à la actuellement accepté de répondre par Joel) ne permet pas de traiter les valeurs NULLES comme des égaux.Les deux lignes suivantes pour (saleprice, saledate) sont admissibles à titre de "distinct" (bien qu'une apparence identique à l'œil humain):

(123, NULL)
(123, NULL)

Passe aussi dans un index unique et presque partout ailleurs, puisque les valeurs NULL ne comparez pas égaux selon le standard SQL.Voir:

Otoh, que, GROUP BY, DISTINCT ou DISTINCT ON () traiter les valeurs NULLES comme des égaux.Utiliser une requête de style en fonction de ce que vous voulez atteindre.Vous pouvez toujours utiliser cette requête plus rapide avec IS NOT DISTINCT FROM au lieu de = pour toutes les comparaisons de rendre NUL comparer l'égalité.Plus:

Si toutes les colonnes sont définis par rapport NOT NULL, il n'y a pas de place pour le désaccord.

Le problème avec votre requête, c'est que lors de l'utilisation d'une clause GROUP BY (qui vous font essentiellement en utilisant différentes), vous pouvez uniquement utiliser les colonnes que vous groupe ou par des fonctions d'agrégation.Vous ne pouvez pas utiliser l'id de colonne, car il y a potentiellement des valeurs différentes.Dans votre cas, il n'y a toujours qu'une seule valeur en raison de la clause HAVING, mais la plupart des SGBDR ne sont pas assez intelligent pour reconnaître que.

Cela devrait fonctionner, en revanche (et n'a pas besoin d'une jointure):

UPDATE sales
SET status='ACTIVE'
WHERE id IN (
  SELECT MIN(id) FROM sales
  GROUP BY saleprice, saledate
  HAVING COUNT(id) = 1
)

Vous pouvez également utiliser MAX AVG ou au lieu de MIN, il est seulement important d'utiliser une fonction qui retourne la valeur de la colonne si il y a une seule ligne correspondante.

Je veux sélectionner les valeurs distinctes d'une colonne 'GrondOfLucht", mais ils doivent être triés dans l'ordre, dans la colonne "sortering'.Je ne peux pas obtenir les valeurs distinctes d'une seule colonne à l'aide de

Select distinct GrondOfLucht,sortering
from CorWijzeVanAanleg
order by sortering

Il sera également donner à la colonne "sortering" et parce que "GrondOfLucht" ET "sortering" n'est pas unique, le résultat sera de TOUTES les lignes.

utiliser le GROUPE pour sélectionner les enregistrements de "GrondOfLucht" dans l'ordre donné par 'sortering

SELECT        GrondOfLucht
FROM            dbo.CorWijzeVanAanleg
GROUP BY GrondOfLucht, sortering
ORDER BY MIN(sortering)

Si votre SGBD ne supporte pas distinctes avec plusieurs colonnes comme ceci:

select distinct(col1, col2) from table

Multi sélection, en général, peut être exécuté en toute sécurité comme suit:

select distinct * from (select col1, col2 from table ) as x

Comme cela peut fonctionner sur la plupart des SGBD, et cela devrait être plus rapide que groupe par la solution que vous êtes en évitant les fonctionnalités de regroupement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top