2014-03-25 50 views
0

我对SQL很陌生,我需要一种方法来返回NULL或0,对于每个外科医生没有记录的年份和季度。只有2个产品系列应该返回(膝盖和肩部),如果外科医生曾经使用过该产品,我只需要缺少年份/季度。例如,如果史密斯,约翰只有膝盖,那么我不需要肩膀的零点。不存在的T-SQL返回记录

这是我到目前为止的查询,但我一直未能弄清楚如何包括没有值的年份和季度。

SELECT q.Surgeon_Name , 
     q.Product_Family , 
     First_Date , 
     q.Year , 
     q.Quarter , 
     CAST(ROUND(q.Monthly_Average, 2) AS MONEY) AS 'Monthly Average' 
FROM (SELECT DISTINCT 
        RTRIM(confirmed_to) AS 'Surgeon_Name' , 
        Product_Family , 
        YEAR(rev_ship_date) AS 'Year' , 
        DATENAME(Quarter, CAST(REV_SHIP_DATE AS DATETIME)) AS 'Quarter' , 
        (SUM(amount)/3) AS 'Monthly_Average' 
      FROM  Vsoicl 
        LEFT JOIN Product_Line_Desc ON vsoicl.PART_ID = Product_Line_Desc.Part_ID 
      WHERE  vsoicl.PRODUCT_LINE <> 'MIRR' 
        AND Product_Family IS NOT NULL 
        AND Product_Family <> 'NULL' 
        AND CONFIRMED_TO <> '' 
        AND REV_SHIP_DATE >= '2013-01-01' 
      GROUP BY CONFIRMED_TO , 
        Product_Family , 
        YEAR(rev_ship_date) , 
        DATENAME(Quarter, CAST(REV_SHIP_DATE AS DATETIME)) 
     ) AS q 
     LEFT JOIN (SELECT DISTINCT 
          RTRIM(confirmed_to) AS 'Surgeon_Name' , 
          Product_Family , 
          CAST(MIN(rev_ship_date) AS DATE) AS 'First_Date' 
        FROM Vsoicl 
          LEFT JOIN Product_Line_Desc ON vsoicl.PART_ID = Product_Line_Desc.Part_ID 
        WHERE vsoicl.PRODUCT_LINE <> 'MIRR' 
          AND Product_Family IS NOT NULL 
          AND Product_Family <> 'NULL' 
        GROUP BY CONFIRMED_TO , 
          Product_Family 
       ) AS f ON q.surgeon_name = f.Surgeon_Name 
          AND q.Product_Family = f.Product_Family 
ORDER BY Surgeon_Name , 
     Product_Family , 
     Year , 
     Quarter 

任何援助将不胜感激。

昨晚我想到了它。

select 
snyq.Surgeon_Name, 
snyq.Product_Family, 
f.First_Date, 
snyq.Year, 
snyq.Quarter, 
sn_sales.[Monthly_Average] 
from 
(
select * from 

    (select distinct rtrim(confirmed_to) as 'Surgeon_Name' 
    ,Product_Family 

    from Vsoicl 
    left join Product_Line_Desc 
    on vsoicl.PART_ID = Product_Line_Desc.Part_ID 

    where vsoicl.PRODUCT_LINE <> 'MIRR' 
    and Product_Family is not null 
    and Product_Family <> 'NULL' 
    and rev_ship_date between '2013-01-01' and GETDATE() 

    Group by CONFIRMED_TO, Product_Family) sn, 

(
select distinct YEAR(rev_ship_date) as Year, datepart(QUARTER,REV_SHIP_DATE) as Quarter 
    from vsoicl 
    where REV_SHIP_DATE between '2013-01-01' and GETDATE()) yq 
) snyq 
left join 
(
    select q.Surgeon_Name 
,q.Product_Family 
,q.Year 
,q.Quarter 
,cast(round(q.Monthly_Average,2) as money) as 'Monthly_Average' 

from (select distinct rtrim(confirmed_to) as 'Surgeon_Name' 
,Product_Family 
,year(rev_ship_date) as 'Year' 
,DATENAME(Quarter, CAST(REV_SHIP_DATE AS DATETIME)) as 'Quarter' 
,(SUM(amount)/3) as 'Monthly_Average' 

from Vsoicl 
left join Product_Line_Desc 
on vsoicl.PART_ID = Product_Line_Desc.Part_ID 

where vsoicl.PRODUCT_LINE <> 'MIRR' 
and Product_Family is not null 
and Product_Family <> 'NULL' 
and CONFIRMED_TO <> '' 
and REV_SHIP_DATE >= '2013-01-01' 

Group by CONFIRMED_TO, Product_Family, YEAR(rev_ship_date), DATENAME(Quarter, CAST(REV_SHIP_DATE AS DATETIME))) as q 
) sn_sales 
on snyq.Surgeon_Name=sn_sales.Surgeon_Name and snyq.Product_Family=sn_sales.Product_Family and snyq.Year=sn_sales.Year and snyq.Quarter=sn_sales.Quarter 
left join (select distinct rtrim(confirmed_to) as 'Surgeon_Name' 
,Product_Family 
,cast(MIN(rev_ship_date) as date) as 'First_Date' 

from Vsoicl 
left join Product_Line_Desc 
on vsoicl.PART_ID = Product_Line_Desc.Part_ID 

where vsoicl.PRODUCT_LINE <> 'MIRR' 
and Product_Family is not null 
and Product_Family <> 'NULL' 
and (STORES_CODE <> 'QU' and SO_STATUS <> 'X' and SO_LINE_STATUS <> 'X' and SHIP_TYPE not IN('O', 'C')) 
and (CUST_PO_ID not like '%Demo%' and CUST_PO_ID not like '%expired%' and CUST_PO_ID not like '%literature%' and CUST_PO_ID not like '%toss%' and CUST_PO_ID not like '%replace%' and CUST_PO_ID not like '%swap%' and CUST_PO_ID not like '%exchange%' and CUST_PO_ID not like '%cancel%' and CUST_PO_ID not like '%duplicate%') 
and ORDER_CLASS <> 'R' 

Group by CONFIRMED_TO, Product_Family) as f 
on snyq.Surgeon_Name=f.Surgeon_Name and snyq.Product_Family=f.Product_Family 
order by Surgeon_Name,Product_Family,Year,Quarter 
+3

也许你需要创建一个myCalendar表这将是一个小桌子,10年(,这就是我,myQQ)所有年/季的利息。这将是一张小桌子,10年只有40行...然后选择myCalendar Left加入myYY = xx和myQQ = zz – donPablo

+0

上面的sql我试过了,结果没有填充缺失的年份/季度。任何其他想法?有没有不同的方法来解决这个问题? –

+0

归结为这一点:[SQL Server:如何选择日期范围内的所有日子,即使某些天没有数据存在](http://stackoverflow.com/questions/5899829/sql-server-how-to-选择所有日子在一个日期范围,甚至如果没有数据存在的话) –

回答

1

我读过快快SQL和修订想到会是

所有年的利息/宿舍创建myCalendar表(myYYYY,MYQQ)。只有40行

然后用十字加入为“正片叠底”的外科医生/产品每个YYYYQQ

SELECT 
    just.Surgeon_Name , 
    just.Product_Family , 

    myYYYY , 
    myQQ , 

    First_Date , 
    [Monthly Average] 

FROM (
    (SELECT DISTINCT 
       RTRIM(confirmed_to) AS 'Surgeon_Name' , 
       Product_Family , 
     FROM  Vsoicl 
     WHERE  PRODUCT_LINE <> 'MIRR' 
      AND Product_Family IS NOT NULL 
      AND Product_Family <> 'NULL' 
      AND CONFIRMED_TO <> '' 
      AND REV_SHIP_DATE >= '2013-01-01' 
    ) as just 

, myCalendar 
     ) 

LEFT JOIN 
    (the above sql) as myV 
    ON just.Surgeon_Name = myV.Surgeon_Name 
    and just.Product_Family= myV.Product_Family 
    and myYYYY = Year 
    and myQQ = Quarter 
+0

昨晚我想出了一个解决方案。看起来和你一样。感谢您的评论! –