PRO C SQL / SQL несколько соединений по первой строке - PullRequest
0 голосов
/ 25 февраля 2020

У меня есть 3 набора данных, и я надеюсь присоединиться к ним в первом ряду, потому что они находятся на разных уровнях. Я назначил базовый набор данных (остальные 2 останутся соединенными с базовым набором данных):

item  state  county  by_county

Apple  MD     aa      4
Apple  DC     bb      3
Apple  DC     cc      2
Pear   VA     cc      6

2-й набор данных:

item state  by_state

Apple  MD    4
Apple  DC    5
Pear   VA    6

3-й набор данных:

item        by_item

Apple        9
Pear         6

Я надеюсь присоединиться к наборам данных, чтобы получить следующий вывод:

item   state  county  by_county   by_state  by_item

Apple   MD     aa     4            4        9
Apple   DC     bb     3            5
Apple   DC     cc     2       
Pear    VA     cc     6            6        6

Вы можете упорядочить по элементам, штатам и округам, чтобы определить первую строку. Это соединение в среде SAS, поэтому разделение по может не работать. (Я не уверен)

Я не могу использовать левое соединение, потому что мне нужно сохранить только одну запись по уровню. Например, в выходном наборе данных сохраняются пропуски, потому что мне нужен только один счетчик элементов (by_item) для всех штатов или округов.

По некоторым причинам люди настаивали, чтобы я опубликовал запрос, который, как я знал, не доставит права Итог:

select a*,b*,c*
from table1 as a
left join table2 as b
on a.item = b.item and a.state = b.state
left join table3 as c
on a.item = c.item;

Спасибо!

Ответы [ 4 ]

1 голос
/ 25 февраля 2020

Просто еще один способ рассмотреть проблему. Как насчет ожидаемой целевой таблицы следующим образом, так что она даже не нарушает значение значения.

    item   state  county  value  

    Apple   MD     aa     4      
    Apple   DC     bb     3
    Apple   DC     cc     2
    Pear    VA     cc     6       

    Apple   MD     ANY    4        
    Apple   DC     ANY    5  
    Pear    VA     ANY    6  

    Apple   ANY    ANY    9   
    Pear    ANY    ANY    6       

Приведенного выше результата можно просто достичь с помощью UNION ALL:

(SELECT 
   item, 
   state, 
   county, 
   by_county as value
 FROM tbl_level3) 
 UNION ALL
(SELECT 
   item, 
   state, 
   "Any" as county, 
   by_state as value
 FROM tbl_level2) 
 UNION ALL 
(SELECT 
   item, 
   "Any" as state, 
   "Any" as county, 
   by_item as value
 FROM tbl_level1);
1 голос
/ 25 февраля 2020

Как я думаю, вы знаете, чтобы получить значения без требования только первого, как это:

SELECT base.item, base.state,  base.county,  base.by_county,   state.by_state,  item.by_item
FROM base
LEFT JOIN state on base.item = state.item and base.state = state.state
LEFT JOIN item on base.item = item.item 

Чтобы изменить это, чтобы просто выбрать первый элемент, мы используем оконные функции - сначала добавьте их в

SELECT base.item, base.state,  base.county,  
       base.by_county, 
       state.by_state,  ROW_NUMBER(partition by base.by_state order by  item,state and county) as RN_S, 
       item.by_item,  ROW_NUMBER(partition by base.by_item order by  item,state and county) as RN_I,
FROM base
LEFT JOIN state on base.item = state.item and base.state = state.state
LEFT JOIN item on base.item = item.item 

Затем добавляем в фильтр:

SELECT item, state, county, by_county,
       CASE WHEN RN_S = 1 THEN by_state ELSE NULL END AS by_state,
       CASE WHEN RN_I = 1 THEN by_item  ELSE NULL END AS by_item
FROM
(
  SELECT base.item, base.state,  base.county,  
       base.by_county, 
       state.by_state,  ROW_NUMBER(partition by base.by_state order by  item,state and county) as RN_S, 
       item.by_item,  ROW_NUMBER(partition by base.by_item order by  item,state and county) as RN_I,
  FROM base
  LEFT JOIN state on base.item = state.item and base.state = state.state
  LEFT JOIN item on base.item = item.item 
) x
0 голосов
/ 05 апреля 2020

вот возможное SAS-решение этой проблемы. Сначала нам нужно объединить все таблицы. Создается новый столбец (skey), который представляет собой просто комбинацию полей элемента и состояния. строки отсортированы по элементам, штатам, округам.

proc sql;
create table all as 
select t1.*, t2.by_state, t3.by_item, catx('||', t1.item, t1.state) as skey
from t1 left join t2
    on t1.item = t2.item and t1.state = t2.state
        left join t3 
            on t1.item = t3.item
order by item, state, county 
;
quit;

затем первая строка для каждого состояния и элемента помечается только как 1. это делается путем добавления столбца "n". Идея состоит в том, чтобы найти первую строку (аналогично выражению row_number на родном sql языке)

data all_1;
set all;
by skey;
if first.skey then n=1;
else n='.';
run;

аналогично предыдущей части, первая строка для каждого элемента помечена как 1.

data all_2;
set all_1;
by item;
if first.item then m=1;
else m='.';
run;

наконец желаемый результат получается двоичным умножением меток первой строки и значений by_item и by_state, как показано ниже:

proc sql;
create table final as 
select item, state, county, by_county, by_state * n as by_state, by_item * m as by_item 
from all_2
;
quit; 
0 голосов
/ 25 февраля 2020

Вам нужно объединить наборы данных, поэтому вам нужно JOIN 3 таблицы. Если вы хотите одну строку для каждого элемента, то вы должны агрегировать ее. Приведенный ниже запрос должен производить по одной строке на элемент.

SELECT item, SUM(by_country) AS by_country_sum, SUM(by_state) AS by_state_sum, SUM(by_item) AS by_item_sum
FROM (
    your query
) a
GROUP BY item;
...