在SQL Server中使用XML PATH命令将多个值组合到一个单元格中

时间:2019-01-23 20:30:38

标签: sql-server

我需要在2列中组合多个值,以在同一行中显示enter code >here,并按一个通用值(即电子邮件enter code >here地址,ID)汇总

我已经能够使用“ FOR XML PATH(''),1,1'')”的一列完成此操作。但是,当我尝试在另一列上使用完全相同的语法和命令时,它不会合并。因此,我得到列A =单个值,并且列B = B1,B2,B3 ..

Declare @StartDate DateTime, @EndDate DateTime  
set @StartDate = Getdate() - 1  
set @EndDate = GetDate()  
SELECT DISTINCT  
pat.email as ADDR,  
pat.fname as INS1,  
STUFF((SELECT ', ' + right(rx.script_no,4)  
FROM cprx rx  
WHERE disp.rx_id = rx.rx_id  
and disp.rxdisp_id = rx.last_rxdisp_id  
and (rx.refills_left is not NULL AND Not(rx.refills_left between -0.1  
and 0.1))  
and len(rx.script_no) = 7  
FOR XML PATH('')),1,1,'')[RxRight4],  
STUFF((SELECT ', ' + left(disp.disp_drug_name,2)  
FROM cprx_disp disp  
WHERE om.order_id = disp.order_id   
FOR XML PATH('')),1,1,'') [DrugLeft2]  
FROM csom om (nolock)  


join cprx_disp disp (nolock) on om.order_id = disp.order_id  
join cprx rx (nolock) on disp.rx_id = rx.rx_id and  (rx.refills_left  
is not NULL AND Not(rx.refills_left between -0.1 and 0.1))  
join cppat pat (nolock) on rx.pat_id = pat.pat_id  
join cppat_ins patins (nolock) on pat.pat_id = patins.pat_id  
WHERE (pat.email <> 'none' and pat.email <> ' ' and pat.email IS NOT  
NULL)  
AND ISNULL(pat.status_cn, 0) IN (0, 1, 2)  
AND ISNULL(pat.pat_status_cn, 1) IN (0, 1)  
and ((dispense_date + (disp_days_supply*.75)) BETWEEN @StartDate and  
@Enddate  
and (rx.refills_left is not NULL AND Not(rx.refills_left between -0.1  
and 0.1))  
AND  rx.store_id in (1)  
AND IsNull(rx.manual_add_yn,0) = 0  
AND rx.script_status_cn = 0  
AND disp.rxdisp_id = rx.last_rxdisp_id)  
Group by Pat.email, Pat.fname, disp.rx_id,disp.rxdisp_id, om.order_id  
Order by INS1,ADDR

我加入了我的联接,以防万一可能是我的问题。因此,我需要将[RxRight4]值全部放在一行中,并按INS1和ADDR>值汇总。它对[DrugLeft2]很好,但对[RxRight4]不好。

例如,我需要结果是这样的:

ADDR              INS1        RxRight4               DrugLeft2
Joe@gmailcom      ABC Group   1234, 4321, 3124       AB, BC, CD

But, what I get is this:

ADDR              INS1        RxRight4               DrugLeft2
Joe@gmail.com     ABC Group   1234                   AB, BC, CD
Joe@gmail.com     ABC Group   4321                   AB, BC, CD
Joe@gmail.com     ABC Group   3124                   AB, BC, CD  

2 个答案:

答案 0 :(得分:0)

在主SELECT表达式中,您有两个带有嵌套SELECT表达式的STUFF函数。在FROM部分中的STUFFs SELECTs中声明的表相对于JOIN中声明的表是独立的。当您在STUFF函数中编写“ FROM cprx rx”和“ FROM cprx_disp disp”时,它们是关于“ JOIN cprx rx”和“ JOIN cprx_disp disp”声明的不同表。

[DrugLeft2]是正确的,因为具有“ WHERE om.order_id = disp.order_id”,但是 [RxRight4]没有直接连接到om表。

下面是您的代码,仅为便于阅读而分解:

      DECLARE @StartDate DateTime, @EndDate DateTime;
      SET @StartDate = Getdate() - 1;
      SET @EndDate = GetDate();

      SELECT DISTINCT  
          pat.email as ADDR,  
          pat.fname as INS1,  
          STUFF((SELECT ', ' + right(rx.script_no,4)  
                 FROM cprx rx  
                 WHERE disp.rx_id = rx.rx_id  
                   AND disp.rxdisp_id = rx.last_rxdisp_id  
                   AND (rx.refills_left IS NOT NULL AND NOT(rx.refills_left BETWEEN -0.1 AND 0.1))  
                 AND LEN(rx.script_no) = 7  
                 FOR XML PATH('')),1,1,'') [RxRight4],  

          STUFF((SELECT ', ' + left(disp.disp_drug_name,2)  
                 FROM cprx_disp disp  
                 WHERE om.order_id = disp.order_id   
                 FOR XML PATH('')),1,1,'') [DrugLeft2]  
      FROM csom om (nolock)  

      JOIN cprx_disp disp (nolock) on om.order_id = disp.order_id  
      JOIN cprx rx (nolock) on disp.rx_id = rx.rx_id AND (rx.refills_left IS NOT NULL AND NOT(rx.refills_left between -0.1 and 0.1))  
      JOIN cppat pat (nolock) on rx.pat_id = pat.pat_id  
      JOIN cppat_ins patins (nolock) on pat.pat_id = patins.pat_id 

      WHERE (pat.email <> 'none' AND pat.email <> ' ' AND pat.email IS NOT NULL)  
            AND ISNULL(pat.status_cn, 0) IN (0, 1, 2)  
            AND ISNULL(pat.pat_status_cn, 1) IN (0, 1)  
            AND ((dispense_date + (disp_days_supply*.75)) BETWEEN @StartDate AND @Enddate 
               AND (rx.refills_left IS NOT NULL AND NOT(rx.refills_left between -0.1 AND 0.1)) 
               AND  rx.store_id in (1)  AND ISNULL(rx.manual_add_yn,0) = 0  AND rx.script_status_cn = 0 AND disp.rxdisp_id = rx.last_rxdisp_id)  

      GROUP BY Pat.email, Pat.fname, disp.rx_id,disp.rxdisp_id, om.order_id  
      ORDER BY INS1,ADDR

答案 1 :(得分:0)

马克,我使用@table变量模拟了您的数据,请注意,我不确定您真正拥有的数据是什么,但我相信这足以解决您的查询。

首先,我将STUFF函数中的嵌套SELECT与主SELECT中的JOIN分开。现在,此嵌套查询将在每个结果行中分别执行。注意,主JOIN中的表具有新的别名disp2和rx2。

第二,在[RxRight4]列的STUFF函数中的嵌套SELECT中,我添加了“ JOIN @cprx_disp disp ON om.order_id = disp.order_id”,通过独立于主SELECT中的disp2表的disp表将om表与cprx rx连接起来

第三,我评论了一些WHERE子句,但我不知道哪个数据可以满足它:

    -- AND LEN(rx.script_no) = 7
    --AND ((dispense_date + (disp_days_supply*.75)) BETWEEN @StartDate AND @Enddate 
    --   AND (rx.refills_left IS NOT NULL AND NOT(rx.refills_left between -0.1 AND 0.1)) 
    --   AND  rx.store_id in (1)  AND ISNULL(rx.manual_add_yn,0) = 0  AND rx.script_status_cn = 0 AND disp.rxdisp_id = rx.last_rxdisp_id)

示例代码现在显示为:

  DECLARE @cppat TABLE (id int, pat_id int, email varchar(20), fname varchar(20), status_cn int, pat_status_cn int );
  DECLARE @cppat_ins TABLE (id int, pat_id int, status_cn int);
  DECLARE @cprx TABLE (id int,rx_id int, last_rxdisp_id int,pat_id int, script_no varchar(10), refills_left int);
  DECLARE @cprx_disp TABLE (id int, rx_id int, order_id int, rxdisp_id int, disp_drug_name varchar(20));
  DECLARE @csom TABLE (order_id int);



  INSERT INTO @cppat (id, pat_id, email, fname, status_cn, pat_status_cn)
  VALUES 
        (1,1,'Joe.gmail.com','ABC GROUP',1,1);

  INSERT INTO @cppat_ins (id, pat_id, status_cn)
  VALUES 
        (1,1,1);

  INSERT INTO @cprx (id, rx_id, last_rxdisp_id, pat_id, script_no, refills_left)
  VALUES 
         (1,1,1,1,'1234',1)
        ,(1,2,1,1,'4321',1)
        ,(1,3,1,1,'3124',1);

 INSERT INTO @cprx_disp (id, rx_id, order_id, rxdisp_id, disp_drug_name)
  VALUES 
          (1,1,1,1,'AB')
         ,(1,2,1,1,'BC')
         ,(1,3,1,1,'CD');

 INSERT INTO @csom (order_id)
 VALUES
        (1);

  DECLARE @StartDate DateTime, @EndDate DateTime;
  SET @StartDate = GETDATE() - 1;
  SET @EndDate = GETDATE();

  SELECT DISTINCT  
      pat.email as ADDR,  
      pat.fname as INS1,  
      STUFF((SELECT ', ' + right(rx.script_no,4)  
             FROM @cprx rx  
             JOIN @cprx_disp disp ON om.order_id = disp.order_id         
             WHERE disp.rx_id = rx.rx_id  
               AND disp.rxdisp_id = rx.last_rxdisp_id  
             AND (rx.refills_left IS NOT NULL AND NOT(rx.refills_left BETWEEN -0.1 AND 0.1))  
             --AND LEN(rx.script_no) = 7  
             FOR XML PATH('')),1,1,'') [RxRight4],  

      STUFF((SELECT ', ' + left(disp.disp_drug_name,2)  
             FROM @cprx_disp disp  
             WHERE om.order_id = disp.order_id   
             FOR XML PATH('')),1,1,'') [DrugLeft2]  
  FROM @csom om 

  JOIN @cprx_disp disp2 ON om.order_id = disp2.order_id  
  JOIN @cprx rx2 ON disp2.rx_id = rx2.rx_id AND (rx2.refills_left IS NOT NULL AND NOT(rx2.refills_left between -0.1 and 0.1))  
  JOIN @cppat pat ON rx2.pat_id = pat.pat_id  
  JOIN @cppat_ins patins ON pat.pat_id = patins.pat_id 

  WHERE (pat.email <> 'none' AND pat.email <> ' ' AND pat.email IS NOT NULL)  
        AND ISNULL(pat.status_cn, 0) IN (0, 1, 2)  
        AND ISNULL(pat.pat_status_cn, 1) IN (0, 1)  
        --AND ((dispense_date + (disp_days_supply*.75)) BETWEEN @StartDate AND @Enddate 
        --   AND (rx.refills_left IS NOT NULL AND NOT(rx.refills_left between -0.1 AND 0.1)) 
        --   AND  rx.store_id in (1)  AND ISNULL(rx.manual_add_yn,0) = 0  AND rx.script_status_cn = 0 AND disp.rxdisp_id = rx.last_rxdisp_id)

  GROUP BY Pat.email, Pat.fname, disp2.rx_id,disp2.rxdisp_id, om.order_id  
  ORDER BY INS1,ADDR

,查询结果为:

   ADDR                 INS1                 RxRight4            DrugLeft2
   -------------------- -------------------- ------------------- --------------------
   Joe.gmail.com        ABC GROUP             1234, 4321, 3124   AB, BC, CD