2017-03-01 3 views
2

Alors voici ma question. Préparez-vous comme il faut un peu de réflexion juste pour envelopper votre tête autour de ce que je suis en train de faire. Je travaille avec Quarterly census employment and wage data. Les données QCEW ont quelque chose appelé codes de suppression. Si une dénomination de données (globalement, quotient de localisation, et sur l'année chaque année chaque trimestre) est supprimée, alors toutes les données pour cette dénomination sont nulles. Je ma table mis en place de la manière suivante (uniquement en vous montrant des colonnes qui sont pertinentes pour la question):Utilisation de l'arithmétique dans SQL sur mes propres colonnes pour remplir une troisième colonne où elle est zéro. (compliqué, seulement lorsque certains critères sont remplis)

A County_Id column,    
Industry_ID column, 
Year column, 
Qtr column, 

colonne Supprimée (0 pour ne pas supprimé et 1 pour suppression),
colonne Data_Category (1 pour global, 2 pour lq, et 3 pour l'année),
colonne Data_Denomination (entre 1 et 8 pour les données spécifiques dans cette catégorie ex: emploi mensuel, salaire imposable, etc.), et une colonne de valeur (qui sera nulle si la Data_Category est supprimée - puisque toutes les valeurs de dénomination de données seront nulles). Maintenant, si les données globales (cat 1) pour, disons, 1991 trimestre 1 est supprimée, mais le trimestre 1 de l'année suivante a globalement et sur l'année (chats 1 et 3) pas supprimé, alors nous pouvons en déduire quoi la valeur serait pour les données supprimées de cette première année, puisque OTY1991q1 = (Overall1991q1 - Overall1990q1). Donc, pour trouver ces données supprimées, nous devrions simplement soustraire nos valeurs de cat 1 (denom 1-8) de nos valeurs cat 3 (denom 1-8) pour remplacer les zéros qui sont dans nos valeurs supprimées de l'année précédente. C'est assez facile à comprendre mathématiquement, la difficulté est qu'il y a des millions de colonnes avec lesquelles vérifier ces critères. J'essaie d'écrire une sorte de requête SQL qui ferait cela pour moi, vérifiez pour vous assurer que Overall-n qtr-n est supprimé, puis regardez pour voir si l'année suivante n'est pas à la fois global et oty, (en Si ces critères sont remplis, effectuez l'arithmétique pour les deux catégories Data_Cat-Data_Denom et remplacez le zéro dans les valeurs Cat-Denom respectives

Vous trouverez ci-dessous un exemple simple (non pertinent). data_cats enlevés) que je l'espère, vous aidera à faire ce que je suis en train de faire à travers.

|CountyID IndustryID Year Qtr Suppressed Data_Cat Data_Denom Value                   
| 5   10  1990 1  1   1  1  0                                      
| 5   10  1990 1  1   1  2  0                                      
| 5   10  1990 1  1   1  3  0                                      
| 5   10  1991 1  0   1  1  5                                      
| 5   10  1991 1  0   1  2  15                                      
| 5   10  1991 1  0   1  3  25                                      
| 5   10  1991 1  0   3  1  20                                      
| 5   10  1991 1  0   3  2  20                                      
| 5   10  1991 1  0   3  3  35 

donc, fondamentalement, ce que nous essayons de faire ici est de prendre l'ensemble des données de chaque catégorie de données (j'ai enlevé lq ~ data_cat 2) parce que ce n'est pas pertinent et data_den om (que j'ai ramené de 8 à 3 pour simplifier) ​​en 1991, soustrayez-le de la valeur globale de 1991 et cela vous donnera le
| valeur pour 1990 cat_1 de l'année précédente. Donc ici data_cat 1 Data_denom 1 serait 15 (20-5), denom 2 serait 5 (20-15), et denom 3 serait 10 (35-25). (Oty 1991q1 - global 1991q1) = 1990q1. J'espère que ça aide. Comme je l'ai dit, le problème n'est pas le calcul, c'est la formulation d'une requête qui va vérifier ce critère des millions et des millions de fois.

+3

Ce sera beaucoup plus facile si vous pouvez fournir des données factices et votre sortie souhaitée à partir de ces données. – iamdave

+0

J'ai un exemple de fichier excel que j'ai mis en place qui simplifie ce que j'essaie de faire, mais c'est la première fois que je pose une question, est-il possible de partager le fichier sur cette page? –

+0

https://senseful.github.io/web-tools/text-table/ - et formatez comme code dans votre question – SqlZim

Répondre

0

Si vous voulez trouver des données supressed qui dispose de 2 lignes de données unsupressed pour l'année prochaine et quart, nous pourrions utiliser croix apply() de faire quelque chose comme ceci:

configuration de test

: http://rextester.com/ORNCFR23551

en utilisant cross apply() pour retourner les lignes avec une valeur dérivée valide:

select t.* 
    , NewValue = cat3.value - cat1.value 
from t 
    cross apply (
     select i.value 
     from t as i 
     where i.CountyID = t.CountyID 
     and i.IndustryID = t.IndustryID 
     and i.Data_Denom = t.Data_Denom 
     and i.Year  = t.Year +1 
     and i.Qtr  = t.Qtr 
     and i.Suppressed = 0 
     and i.Data_Cat = 1 
) cat1 
    cross apply (
     select i.value 
     from t as i 
     where i.CountyID = t.CountyID 
     and i.IndustryID = t.IndustryID 
     and i.Data_Denom = t.Data_Denom 
     and i.Year  = t.Year +1 
     and i.Qtr  = t.Qtr 
     and i.Suppressed = 0 
     and i.Data_Cat = 3 
) cat3 
where t.Suppressed = 1 
    and t.Data_Cat = 1 

rendements:

+----------+------------+------+-----+------------+----------+------------+-------+----------+ 
| CountyID | IndustryID | Year | Qtr | Suppressed | Data_Cat | Data_Denom | Value | NewValue | 
+----------+------------+------+-----+------------+----------+------------+-------+----------+ 
|  5 |   10 | 1990 | 1 |   1 |  1 |   1 |  0 |  15 | 
|  5 |   10 | 1990 | 1 |   1 |  1 |   2 |  0 |  5 | 
|  5 |   10 | 1990 | 1 |   1 |  1 |   3 |  0 |  10 | 
+----------+------------+------+-----+------------+----------+------------+-------+----------+ 


aide outer apply() pour retourner toutes les lignes

select t.* 
    , NewValue = coalesce(nullif(t.value,0),cat3.value - cat1.value,0) 
from t 
    outer apply (
     select i.value 
     from t as i 
     where i.CountyID = t.CountyID 
     and i.IndustryID = t.IndustryID 
     and i.Data_Denom = t.Data_Denom 
     and i.Year  = t.Year +1 
     and i.Qtr  = t.Qtr 
     and i.Suppressed = 0 
     and i.Data_Cat = 1 
) cat1 
    outer apply (
     select i.value 
     from t as i 
     where i.CountyID = t.CountyID 
     and i.IndustryID = t.IndustryID 
     and i.Data_Denom = t.Data_Denom 
     and i.Year  = t.Year +1 
     and i.Qtr  = t.Qtr 
     and i.Suppressed = 0 
     and i.Data_Cat = 3 
) cat3 

retourne:

+----------+------------+------+-----+------------+----------+------------+-------+----------+ 
| CountyID | IndustryID | Year | Qtr | Suppressed | Data_Cat | Data_Denom | Value | NewValue | 
+----------+------------+------+-----+------------+----------+------------+-------+----------+ 
|  5 |   10 | 1990 | 1 |   1 |  1 |   1 |  0 |  15 | 
|  5 |   10 | 1990 | 1 |   1 |  1 |   2 |  0 |  5 | 
|  5 |   10 | 1990 | 1 |   1 |  1 |   3 |  0 |  10 | 
|  5 |   10 | 1991 | 1 |   0 |  1 |   1 |  5 |  5 | 
|  5 |   10 | 1991 | 1 |   0 |  1 |   2 | 15 |  15 | 
|  5 |   10 | 1991 | 1 |   0 |  1 |   3 | 25 |  25 | 
|  5 |   10 | 1991 | 1 |   0 |  3 |   1 | 20 |  20 | 
|  5 |   10 | 1991 | 1 |   0 |  3 |   2 | 20 |  20 | 
|  5 |   10 | 1991 | 1 |   0 |  3 |   3 | 35 |  35 | 
+----------+------------+------+-----+------------+----------+------------+-------+----------+ 
+0

Eh bien, bien sûr, mais aucun des exemples de votre lien ne s'applique réellement à * cette requête *. (Nous ne nous joignons pas à une inégalité, ou sur 'TOP n', ou faisons quelque chose qui ne peut pas être géré avec' INNER JOIN'.) Si la conception physique est bonne, le 'INNER JOIN' fonctionnera bien; Si ce n'est pas le cas, aucune requête ne fonctionnera correctement. –

+0

Merci SqlZim, votre code fonctionne aussi bien. Y a-t-il un moyen de le modifier d'une manière qui permet que cela se produise sur plusieurs années? Supposons que le même phénomène se soit produit entre les années 1992 et 1993, mais que vous vouliez mettre à jour les deux valeurs inférées des quatre années avec le même énoncé select. Y a-t-il un moyen de le faire, ou cela demande-t-il trop? –

+0

@ J.Jack Je ne suis pas sûr de comprendre votre question. Si deux années consécutives sont supprimées, comment obtenez-vous la valeur Cat3 pour l'année supprimée à utiliser sur la deuxième année supprimée? – SqlZim

0

MISE À JOUR 1 - Correction des noms de colonnes

MISE À JOUR 2 - alias améliorés en 2ème requête


Ok, je pense que je comprends.

Si vous êtes juste vouloir faire une seule inférence, alors ce qui suit peut vous aider. (Si ce n'est que la première des nombreuses inférences que vous voulez faire en comblant les lacunes de données, vous pouvez trouver qu'une méthode différente mène à une solution plus efficace pour les faire tous/tous, mais je suppose que vous traverserez ce pont ...)

Bien qu'une grande partie de la logique de base reste le même, comment vous tweak cela dépend si vous voulez une requête juste pour fournir les valeurs que vous déduis (par exemple pour conduire une déclaration UPDATE), ou si vous souhaitez utiliser cette logique en ligne dans une requête plus importante. Pour des raisons de performances, je pense que le premier a plus de sens (surtout si vous pouvez faire la mise à jour une seule fois et lire le jeu de données plusieurs fois), donc je commencerai par cadrer les choses et revenir à l'autre dans un instant.

On dirait que vous avez une seule table (je l'appellerai QCEW) avec toutes ces colonnes. Dans ce cas, l'utilisation se joint à associer à chaque point de données globale supprimée (c_oa dans le code suivant) avec le correspondant datapoints globale et OTY d'un an plus tard:

SELECT c_oa.*, n_oa.value - n_oty.value inferred_value 
    FROM   QCEW c_oa --current yr/qtr overall 
     inner join QCEW n_oa --next yr (same qtr) overall 
       on c_oa.countyId = n_oa.countyId 
      and c_oa.industryId = n_oa.industryId 
      and c_oa.year = n_oa.year - 1 
      and c_oa.qtr = n_oa.qtr 
      and c_oa.data_denom = n_oa.data_denom 
     inner join QCEW n_oty --next yr (same qtr) over-the-year 
       on c_oa.countyId = n_oty.countyId 
      and c_oa.industryId = n_oty.industryId 
      and c_oa.year = n_oty.year - 1 
      and c_oa.qtr = n_oty.qtr 
      and c_oa.data_denom = n_oty.data_denom 
WHERE c_oa.SUPPRESSED = 1 
    AND c_oa.DATA_CAT = 1 
    AND n_oa.SUPPRESSED = 0 
    AND n_oa.DATA_CAT = 1 
    AND n_oty.SUPPRESSED = 0 
    AND n_oty.DATA_CAT = 3 

Maintenant, il semble que la table est grande, et nous Je viens de rejoindre 3 instances de celui-ci; Pour que cela fonctionne, vous aurez besoin d'une bonne conception physique (index/statistiques appropriés pour les colonnes de jointure, etc.). Et c'est pourquoi je suggère de faire une mise à jour basée sur la requête ci-dessus une fois; bien sûr, cela peut durer longtemps, mais alors vous pouvez lire les valeurs inférées en un rien de temps.

Mais si vous voulez vraiment fusionner cela directement dans une requête de données, vous pouvez le modifier pour afficher toutes les valeurs, avec des valeurs inférées mélangées.Nous devons passer à joint à ce faire extérieur, et je vais faire des choses avec des conditions de jointure peu étranges pour le faire rentrer ensemble:

SELECT src.COUNTYID 
    , src.INDUSTRYID 
    , src.YEAR 
    , src.QTR 
    , case when (n_oa.value - n_oty.value) is null 
      then src.suppressed 
      else 2 
     end as SUPPRESSED_CODE -- 0=NOT SUPPRESSED, 1=SUPPRESSED, 2=INFERRED 
    , src.DATA_CAT 
    , src.DATA_DENOM 
    , coalesce(n_oa.value - n_oty.value, src.value) as VALUE 
    FROM   QCEW src  --a source row from which we'll generate a record 
     left join QCEW n_oa --next yr (same qtr) overall (if src is suppressed/overall) 
      on src.countyId = n_oa.countyId 
      and src.industryId = n_oa.industryId 
      and src.year = n_oa.year - 1 
      and src.qtr = n_oa.qtr 
      and src.data_denom = n_oa.data_denom 
      and src.SUPPRESSED = 1 and n_oa.SUPPRESSED = 0 
      and src.DATA_CAT = 1 and n_oa.DATA_CAT = 1 
     left join QCEW n_oty --next yr (same qtr) over-the-year (if src is suppressed/overall) 
      on src.countyId = n_oty.countyId 
      and src.industryId = n_oty.industryId 
      and src.year = n_oty.year - 1 
      and src.qtr = n_oty.qtr 
      and src.data_denom = n_oty.data_denom 
      and src.SUPPRESSED = 1 and n_oty.SUPPRESSED = 0 
      and src.DATA_CAT = 1 and n_oty.DATA_CAT = 3 
+0

Est-ce que ce deuxième jeu de code fonctionnerait avec la table formatée comme ci-dessus? Je suis aussi un peu confus à propos de vous en utilisant le c_oa. en tant que point de données global supprimé. Vous pouvez sélectionner des choses qui n'existent pas encore? Je m'excuse, mais comme je l'ai dit, j'ai seulement commencé à apprendre le SQL en janvier, alors que je le décroche rapidement, il y a encore beaucoup de choses que je ne connais pas parce que je n'ai pas eu à le faire. –

+0

Donc, prendre les questions une à la fois ... –

+0

** Cela fonctionnera-t-il avec une table formatée comme ci-dessus? ** Sauf si quelque chose me manque, ce qui précède correspond à mes hypothèses (sauf les noms de colonnes, que je vais mettre à jour). Je vais essayer de voir s'il me manque quelque chose; mais vous pouvez également tester la requête sur un échantillon de données et voir si elle fonctionne comme vous le souhaitez. –