SQL запрашивает несколько строк в одну, если выполнены критерии

#sql #sql-server-2008

#sql #sql-server-2008

Вопрос:

Я новичок в этом, и это не мои данные. Мы пытаемся объединить несколько записей в одну запись для получения результатов запроса.

Для упрощения таблиц и объема данных должно быть достаточно следующих двух таблиц:

Таблица 1

 PRVDR_NUM | RPT_REC_NUM  
013          1234
014          4567
  

Таблица 2

 RPT_REC_NUM |  WKSHT_CD | LINE_NUM | ITM_VAL_NUM
1234             f1         3           30
1234             f1         9           3
1234             e2       100           100
4567             f1         3           20
4567             f1         9           8
4567             e2       100           100
  

Первая часть состоит в том, чтобы получить все записи, где значение ITM_NUM_CAL находится в диапазоне от 25 до 50 для WKSHT_CD f1 и LINE_NUM 3, что значение ITM_NUM_VAL равно доходу.

 SELECT      r.PRVDR_NUM as Provider, 
            r.RPT_REC_NUM as 'Report Record', 
            n.ITM_VAL_NUM as Revenue

FROM        Table 1 r
        left outer join Table 2 n on 
        r.RPT_REC_NUM = n.RPT_REC_NUM

WHERE (n.WKSHT_CD = 'f1') and (n.LINE_NUM = '3')
        and (n.ITM_VAL_NUM > 25) and (n.ITM_VAL_NUM < 50)
        and left(r.PRVDR_NUM, 2) in ('01','04','11','18','25','26','34','44','49')
  

Итак, наши результаты:

 Provider |  Report Record | Revenue 
 013           1234         30    
  

Но мы также хотим иметь возможность извлекать соответствующие ITM_VAL_NUM для WKSHT_CD f1 и LINE_NUM 9, которые мы будем называть cost.

Таким образом, результаты должны быть:

 Provider |  Report Record | Revenue | Cost
 013           1234          30         3
  

Заранее большое спасибо.

Редактировать

Я полагаю, что это последний запрос, который я искал после некоторых маневров и добавления новой переменной CLMN_NUM, которая является еще одним столбцом в table2.

 SELECT r.PRVDR_NUM as Provider, 
       r.RPT_REC_NUM as 'Report Record', 
       n.ITM_VAL_NUM as Revenue,
       n2.ITM_VAL_NUM as 'Cost',
       n3.ITM_VAL_NUM as 'Visits'

FROM table1 r
    LEFT OUTER JOIN table2 n on r.RPT_REC_NUM = n.RPT_REC_NUM
    LEFT OUTER JOIN table2 n2 on n.WKSHT_CD = n2.WKSHT_CD
    and n.RPT_REC_NUM = n2.RPT_REC_NUM and n2.LINE_NUM = 9
    LEFT OUTER JOIN table2 n3 on r.RPT_REC_NUM = n3.RPT_REC_NUM 
    and n3.WKSHT_CD = 'e2' and n3.LINE_NUM = 100 and n3.CLMN_NUM = xxxx  

WHERE (n.WKSHT_CD = 'f1') 
AND (n.LINE_NUM = '3')
AND (n.ITM_VAL_NUM > 25) 
AND (n.ITM_VAL_NUM < 50)
AND left(r.PRVDR_NUM, 2) in ('01','04','11','18','25','26','34','44','49')
  

Ответ №1:

Пара способов:

Подзапрос

 SELECT r.PRVDR_NUM as Provider, 
       r.RPT_REC_NUM as 'Report Record', 
       n.ITM_VAL_NUM as Revenue
       (SELECT ITM_VAL_NUM 
        FROM Table2 
        WHERE WKSHT_CD = n.WKSHT_CD 
        AND LINE_NUM = 9) AS Cost
FROM Table1 r
    LEFT OUTER JOIN Table2 n on r.RPT_REC_NUM = n.RPT_REC_NUM
WHERE (n.WKSHT_CD = 'f1') 
AND (n.LINE_NUM = '3')
AND (n.ITM_VAL_NUM > 25) 
AND (n.ITM_VAL_NUM < 50)
AND left(r.PRVDR_NUM, 2) in ('01','04','11','18','25','26','34','44','49')
  

Другое ОБЪЕДИНЕНИЕ

 SELECT r.PRVDR_NUM as Provider, 
       r.RPT_REC_NUM as 'Report Record', 
       n.ITM_VAL_NUM as Revenue
       n2.Cost
FROM Table1 r
    LEFT OUTER JOIN Table2 n on r.RPT_REC_NUM = n.RPT_REC_NUM
    LEFT OUTER JOIN Table2 n2 on n.WKSHT_CD = n2.WKSHT_CD
        AND LINE_NUM = 9
WHERE (n.WKSHT_CD = 'f1') 
AND (n.LINE_NUM = '3')
AND (n.ITM_VAL_NUM > 25) 
AND (n.ITM_VAL_NUM < 50)
AND left(r.PRVDR_NUM, 2) in ('01','04','11','18','25','26','34','44','49')
  

Комментарии:

1. Спасибо за быстрые ответы, когда я пробую ваше решение для подзапросов, я получаю сообщение для более чем 1 значения. Когда я пробую ваше решение JOIN после некоторой модификации, я заставляю его работать, но в итоге получается слишком много строк, как будто это потянуло на себя все затраты.

2. В обоих случаях это было бы из-за данных, и я предполагаю, что вы предоставляете только выборку. Вам нужно было бы добавить условия, гарантирующие возврат только 1 записи.

3. Спасибо за вашу помощь, Дастин, я отредактировал свой пост с некоторыми изменениями и дополнениями, будет ли это нормально?

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

Ответ №2:

Вы можете, выполнив CASE / WHEN для ваших рассматриваемых столбцов, но разрешив ОБА значения LINE_NUM в вашем where тоже… Использование ОБЪЕДИНЕНИЯ предотвратит нулевые значения в случае отсутствия записей для одной стороны, другой или обеих для доходов / затрат соответственно. Вы могли бы просто использовать то же самое для любых других значений «LINE_NUM», которые вы хотели бы включить.

 SELECT
      r.PRVDR_NUM as Provider,
      r.RPT_REC_NUM as 'Report Record',
      COALESCE( CASE WHEN n.LINE_NUM = 3 THEN n.ITM_VAL_NUM ELSE 0 END, 0 ) as Revenue,
      COALESCE( CASE WHEN n.LINE_NUM = 9 THEN n.ITM_VAL_NUM ELSE 0 END, 0 ) as Costs
   from
      Table_1 r
         left join Table_2 n
            on r.RPT_REC_NUM = n.RPT_REC_NUM
            AND n.WKSHT_CD = 'f1'
            AND n.LINE_NUM in ( '3', '9')
            AND n.ITM_VAL_NUM between 25 and 50
   where
      left(r.PRVDR_NUM, 2) in ('01','04','11','18','25','26','34','44','49') 
  

Комментарии:

1. Я пытался это сделать и пробовал некоторые модификации, но каждый раз получаю нули в обоих полях.

Ответ №3:

 SELECT
  Provider        = r.PRVDR_NUM,
  [Report Record] = r.RPT_REC_NUM,
  Revenue         = MIN(CASE n.LINE_NUM WHEN '3' THEN n.ITM_VAL_NUM),
  Cost            = MIN(CASE n.LINE_NUM WHEN '9' THEN n.ITM_VAL_NUM)
FROM Table1 r
  INNER JOIN Table2 n ON r.RPT_REC_NUM = n.RPT_REC_NUM
WHERE n.WKSHT_CD = 'f1' AND n.LINE_NUM IN ('3', '9')
  AND n.ITM_VAL_NUM > 25 AND n.ITM_VAL_NUM < 50
  AND LEFT(r.PRVDR_NUM, 2) IN ('01','04','11','18','25','26','34','44','49')
GROUP BY
  r.PRVDR_NUM,
  r.RPT_REC_NUM