2010-07-09 4 views
2

Mon problème:
J'ai une table avec une Channel <int> et une colonne Value <float>, ainsi qu'un horodatage et deux autres colonnes avec des données supplémentaires. Channel est soit 1 ou 2, et il y a 1 ou 2 lignes qui ont tout sauf canal et valeur identique.déclaration Tricky SQL SELECT - combiner deux lignes dans deux colonnes

Ce que je voudrais faire est de sélectionner ces données dans un nouveau formulaire, où les deux canaux apparaissent en colonnes. J'ai essayé de faire quelque chose avec GROUP BY, mais je ne pouvais pas comprendre comment obtenir les valeurs dans les colonnes correctes basées sur le canal sur la même rangée. , Ici il est
Pour ceux d'entre vous qui regardez plutôt les données que je l'ai et les données que je veux et la figure à partir de là:

Exemple. Ce que j'ai:

Channel Value  Timestamp    OtherStuff 
1   0.2394  2010-07-09 13:00:00  'some other stuff' 
2   1.2348  2010-07-09 13:00:00  'some other stuff' 
1   24.2348  2010-07-09 12:58:00  'some other stuff' 
2   16.3728  2010-07-09 12:58:00  'some other stuff' 
1   12.284  2010-07-09 13:00:00  'unrelated things' 
2   9.6147  2010-07-09 13:00:00  'unrelated things' 

Ce que je veux:

Value1  Value2  Timestamp    OtherStuff 
0.2394  1.2348  2010-07-09 13:00:00  'some other stuff' 
24.2348 16.3728  2010-07-09 12:58:00  'some other stuff' 
12.284  9.6147  2010-07-09 13:00:00  'unrelated things' 

Mise à jour en réponse à certaines questions qui ont arised dans les commentaires, et quelques questions de suivi/clarifications:

  • Oui, c'est la combinaison de Timestamp et OtherStuff qui lie les deux lignes ensemble. (OtherStuff est en fait plus d'une colonne, mais j'ai simplifié par souci de brièveté.) Il y a aussi quelques autres colonnes qui ne sont pas nécessairement égales, mais qui devraient être conservées telles quelles.

  • Le tableau en question est déjà jointe à partir de deux tables, où Value, Channel et Timestamp vient d'un d'entre eux, et le reste (un total de 7 autres colonnes, dont 4 sont toujours égaux pour « liés » les rangées, et les trois autres ne le sont généralement pas). Il y a eu quelques suggestions en utilisant INNER JOIN - cela fonctionnera-t-il encore si je suis déjà en train de joindre des choses ensemble (même si je n'ai pas de myTable pour se rejoindre)?

  • Il y a beaucoup de lignes avec le même horodatage, donc je besoin d'informations des deux tables, je me joins à comprendre les lignes à relier entre eux.

  • J'ai beaucoup de données. L'entrée provient d'appareils de mesure répartis dans tout le pays, et la plupart d'entre eux (sinon tous) téléchargent des mesures (jusqu'à 4 canaux) toutes les 2 minutes. À l'heure actuelle, nous avons environ 1000 appareils en ligne, ce qui signifie en moyenne environ 1000 lignes par minute. Je dois prendre en compte des valeurs qui sont au moins 3, de préférence 6, heures, ce qui signifie 180 000 à 360 000 lignes dans le tableau avec le canal, la valeur et l'horodatage.

+0

ce qui relie les 2 lignes? horodatage et otherstuff? – gbn

+0

Juste posé une question qui est inverse de ceci :)! – Baaju

Répondre

4

Tant que vous avez quelque chose qui relie les 2 lignes, quelque chose comme ça

SELECT 
    c1.Value AS Value1, c2.Value AS Value2, c1.timestamp, c2.otherstuff 
FROM 
    MyTable c1 
    JOIN 
    MyTable c2 ON c1.timestamp = c2.timestamp AND c1.otherstuff = c2.otherstuff 
WHERE 
    c1.Channel = 1 AND c2.Channel = 2 

Si vous n'avez rien qui relie les 2 lignes, il ne peut probablement pas être fait car comment savez-vous qu'ils sont jumelés?

Si vous avez 1 ou 2 lignes (edit: et ne sais pas quelle valeur le canal que vous avez)

SELECT 
    c1.Value AS Value1, c2.Value AS Value2, c1.timestamp, c2.otherstuff 
FROM 
    (
    SELECT Value, timestamp, otherstuff 
    FROM MyTable 
    WHERE Channel = 1 
    ) c1   
    FULL OUTER JOIN 
    (
    SELECT Value, timestamp, otherstuff 
    FROM MyTable 
    WHERE Channel = 2 
    ) c2 ON c1.timestamp = c2.timestamp AND c1.otherstuff = c2.otherstuff     
+0

J'ai 1 * ou * 2 lignes. Est-ce que la deuxième approche, même si je ne sais pas nécessairement quel canal j'ai si je n'ai qu'une seule rangée? –

+0

@tomas lycken: Je l'ai mis à jour pour ce cas – gbn

+0

J'ai peur de trop simplifier la structure de ma table - voir les mises à jour de ma question. Dois-je résoudre le fait que j'ai deux tables jointes en joignant d'abord à une variable de table, ou y a-t-il une bonne façon de le faire même si toutes les colonnes ne proviennent pas de la même table? Je suppose que je pourrais simplement rejoindre l'autre table, mais où dois-je faire cela pour une performance optimale? (La requête prend déjà presque une minute ...) –

-1
SELECT a.Value as Value1, b.Value as Value2, 
a.TimeStamp, a.OtherStuff 
FROM myTable a INNER JOIN myTable b 
ON a.OtherStuff = b.OtherStuff and a.TimeStamp = b.TimeStamp 
WHERE a.Channel = 1 AND b.Channel = 2 

écrit sans éditeur de requête. S'il vous plaît soyez gentil :)

EDIT: INNER JOIN pourrait également être utilisé ici. EDIT2: corrigé avec INNER JOIN. Ne vous précipitez pas downvote :)

+0

-1 pour ne pas utiliser un JOIN. Il est assez difficile pour les autres développeurs de voir ce qui se passe avec la syntaxe FROM table1, table2. – JonH

+0

c'est faux de toute façon ainsi que la mauvaise forme. "a.TimeStamp = 1 ET b.TimeStamp = 2"? – gbn

+0

@gbn: Oui. Je l'ai corrigé. Merci à SO, il y a une fonction d'édition (imaginez les downvotes autrement). – shahkalpesh

0

Quelque chose comme ...

SELECT MAX(CASE Channel WHEN 1 THEN Value ELSE 0 END) AS Value1, 
     MAX(CASE Channel WHEN 2 THEN Value ELSE 0 END) AS Value2, 
     Timestamp, 
     OtherStuff 
FROM  {tablename} 
GROUP BY Timestamp, OtherStuff 

(Je nai testé cela!) (et cela suppose que votre valeur est toujours positive!)

Alternativement (voir commentaires ci-dessous) ...

SELECT SUM(CASE Channel WHEN 1 THEN Value ELSE 0 END) AS Value1, 
     SUM(CASE Channel WHEN 2 THEN Value ELSE 0 END) AS Value2, 
     Timestamp, 
     OtherStuff 
FROM  {tablename} 
GROUP BY Timestamp, OtherStuff 
+0

Malheureusement, je ne peux pas supposer que la valeur est toujours positive. Mais merci quand même =) –

+0

Ok, bien s'il y a toujours exactement 1 ligne pour le canal 1 et exactement 1 ligne pour le canal 2 (pour chaque horodatage) alors voir mon alternative (ci-dessus) – barrylloyd

+0

Malheureusement ce n'est pas le cas non plus - à la fois * l'horodatage et l'autre chose (plusieurs colonnes) à distinguer. Comme vous le voyez dans mon exemple, il peut y avoir deux lignes avec le canal 1 et l'horodateur 13:00 qui n'appartiennent pas à la même ligne "liée". –