如何获得给定周数的总数

时间:2018-01-09 08:00:01

标签: sql-server tsql

我正在尝试创建一个weekofyear返回的查询,如果该周有4个或更多DISTINCT(DELIVERYDATE),则返回值。因此,如果只有3天,它将返回一个空值。如果是4个或更多DISTINCT(DELIVERYDATE),则返回' weekofyear'值。

SELECT  READYDATE,TOTALAMOUNT,ORDER_TRACK_NUMBER,
(CONVERT(VARCHAR(4),LEFT(DELIVERYDATE,4))  + '' + CONVERT(VARCHAR(4),DATEPART( wk, DELIVERYDATE))) AS WEEKOfYear
FROM CurrentOrder  COrder
WHERE
  COrder.CANCELLED = 0 
  AND COrder.DELIVERYDATE>='20171116'
  AND COrder.DELIVERYDATE<='20171116'
  ORDER BY DISPID

查询后我想要的预期输出

READYDATE   TOTALAMOUNT ORDERNUM    DELIVERYDATE WEEKOfYear  
2017-11-16  11.24       6784230     2017-11-16  201746   
2017-11-16  0.00        6788903     2017-11-16  201746   
2017-11-16  91.85       6789075S    2017-11-16  201746   
2017-11-16  640.00      6789080S    2017-11-16  201746   
2017-11-16  0.00        6789213S    2017-11-16  201746   
2017-11-15  0.00        6789098S    2017-11-15  NULL     
2017-11-15  0.00        6789103S    2017-11-15  NULL     
2017-11-15  0.00        6789110S    2017-11-15  NULL     
2017-11-13  250.00      6789751S    2017-11-13  NULL     
2017-11-13  250.00      6789756S    2017-11-13  NULL     
2017-11-13  25.00       6789773S    2017-11-13  NULL     
2017-11-14  242.00      6789779S    2017-11-14  201746   
2017-11-14  23.88       6789816S    2017-11-14  201746   
2017-11-14  190.00      6789833S    2017-11-14  201746   
2017-11-14  215.00      6789845S    2017-11-14  201746   
2017-11-14  108.00      6789873S    2017-11-14  201746

    CREATE TABLE [dbo].[CurrentOrder](
    [OrderId] [int] NOT NULL,
    [ORDER_TRACK_NUMBER] [varchar](50) NULL,
    [TOTALAMOUNT] [decimal](18, 10) NULL,
    [READYDATE] [date] NULL,
    [DELIVERYDATE] [date] NULL,
    [CANCELLED] [tinyint] NULL,
    [DispID] [int] NULL,
PRIMARY KEY CLUSTERED 
(
    [OrderId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

    INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (1, N'6784230', CAST(11.0000000000 AS Decimal(18, 10)), CAST(0x883D0B00 AS Date), CAST(0x883D0B00 AS Date), 0, 56)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (2, N'6788903', CAST(0.0000000000 AS Decimal(18, 10)), CAST(0x883D0B00 AS Date), CAST(0x883D0B00 AS Date), 0, 56)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (3, N'6789075S', CAST(92.0000000000 AS Decimal(18, 10)), CAST(0x883D0B00 AS Date), CAST(0x883D0B00 AS Date), 0, 56)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (4, N'6789080S', CAST(640.0000000000 AS Decimal(18, 10)), CAST(0x883D0B00 AS Date), CAST(0x883D0B00 AS Date), 0, 56)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (5, N'6789213S', CAST(0.0000000000 AS Decimal(18, 10)), CAST(0x883D0B00 AS Date), CAST(0x883D0B00 AS Date), 0, 56)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (6, N'6789098S', CAST(0.0000000000 AS Decimal(18, 10)), CAST(0x873D0B00 AS Date), CAST(0x873D0B00 AS Date), 0, 66)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (7, N'6789103S', CAST(0.0000000000 AS Decimal(18, 10)), CAST(0x873D0B00 AS Date), CAST(0x873D0B00 AS Date), 0, 66)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (8, N'6789110S', CAST(0.0000000000 AS Decimal(18, 10)), CAST(0x873D0B00 AS Date), CAST(0x873D0B00 AS Date), 0, 66)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (9, N'6789751S', CAST(250.0000000000 AS Decimal(18, 10)), CAST(0x853D0B00 AS Date), CAST(0x853D0B00 AS Date), 0, 65)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (10, N'6789756S', CAST(250.0000000000 AS Decimal(18, 10)), CAST(0x853D0B00 AS Date), CAST(0x853D0B00 AS Date), 0, 65)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (11, N'6789773S', CAST(25.0000000000 AS Decimal(18, 10)), CAST(0x853D0B00 AS Date), CAST(0x853D0B00 AS Date), 0, 65)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (12, N'6789779S', CAST(242.0000000000 AS Decimal(18, 10)), CAST(0x863D0B00 AS Date), CAST(0x863D0B00 AS Date), 0, 39)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (13, N'6789816S', CAST(24.0000000000 AS Decimal(18, 10)), CAST(0x863D0B00 AS Date), CAST(0x863D0B00 AS Date), 0, 39)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (14, N'6789833S', CAST(190.0000000000 AS Decimal(18, 10)), CAST(0x863D0B00 AS Date), CAST(0x863D0B00 AS Date), 0, 39)
INSERT [dbo].[CurrentOrder] ([OrderId], [ORDER_TRACK_NUMBER], [TOTALAMOUNT], [READYDATE], [DELIVERYDATE], [CANCELLED], [DispID]) VALUES (15, N'6789845S', CAST(215.0000000000 AS Decimal(18, 10)), CAST(0x863D0B00 AS Date), CAST(0x863D0B00 AS Date), 0, 39)

说明: - DeliveryDate - 2017-11-16超过4,因此会显示WEEKOfYear中的值,但对于DeliveryDate&2017; 2017-11-15 has only three orders so this is displaying Null same as for the date 2017-11- 13 . But again DELIVERDATE 2017-11-14`在该日期有超过4个订单,因此显示的是WEEKOfYear。

提前感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

您可以使用count()over()子句来获取每个交付日期的行数,以及确定是否显示weekOfYear或null的情况,如下所示:

SELECT  READYDATE,
        TOTALAMOUNT,
        ORDER_TRACK_NUMBER, 
        CASE WHEN COUNT(*) OVER(PARTITION BY DELIVERYDATE) > 3 THEN
            CAST(DATEPART(YEAR, DELIVERYDATE) as char(4)) +
            CAST(DATEPART(WEEK, DELIVERYDATE) as char(2))
        ELSE
            NULL
        END As WeekOfYear
FROM CurrentOrder
WHERE CANCELLED = 0 
ORDER BY DISPID

结果:

READYDATE       TOTALAMOUNT         ORDER_TRACK_NUMBER  WeekOfYear
2017-11-14      242,0000000000      6789779S            201746
2017-11-14      24,0000000000       6789816S            201746
2017-11-14      190,0000000000      6789833S            201746
2017-11-14      215,0000000000      6789845S            201746
2017-11-16      11,0000000000       6784230             201746
2017-11-16      0,0000000000        6788903             201746
2017-11-16      92,0000000000       6789075S            201746
2017-11-16      640,0000000000      6789080S            201746
2017-11-16      0,0000000000        6789213S            201746
2017-11-13      250,0000000000      6789751S            NULL
2017-11-13      250,0000000000      6789756S            NULL
2017-11-13      25,0000000000       6789773S            NULL
2017-11-15      0,0000000000        6789098S            NULL
2017-11-15      0,0000000000        6789103S            NULL
2017-11-15      0,0000000000        6789110S            NULL

答案 1 :(得分:1)

此方法使用common table expression (CTE)查找包含4个或更多记录的每个交货日期。使用交货日期计算一周中的一周。然后,我们可以使用outer join将新字段附加到原始表中的每个匹配记录。

WITH DWeek AS
(
    -- Calculate week of year for every delivery date with 4 or more records.
    SELECT
        DELIVERYDATE,
        (CONVERT(VARCHAR(4),LEFT(DELIVERYDATE,4))  + '' + CONVERT(VARCHAR(4),DATEPART( wk, DELIVERYDATE))) AS WEEKOfYear
    FROM
        CurrentOrder
    WHERE
        DELIVERYDATE IS NOT NULL
        AND CANCELLED = 0 
        AND DELIVERYDATE >= '20171114'
        AND DELIVERYDATE <= '20171116'
    GROUP BY    
        DELIVERYDATE
    HAVING
        COUNT(1) >= 4
)
SELECT
    co.*,
    s.WEEKOfYear
FROM
    CurrentOrder AS co
        LEFT OUTER JOIN DWeek AS s     ON s.DELIVERYDATE = co.DELIVERYDATE
;

返回

OrderId ORDER_TRACK_NUMBER  TOTALAMOUNT     READYDATE   CANCELLED   DELIVERYDATE    WEEKOfYear
1       6784230             11.2400000000   2017-11-16  0           2017-11-16      201746
2       6788903             0.0000000000    2017-11-16  0           2017-11-16      201746
3       6789075S            91.8500000000   2017-11-16  0           2017-11-16      201746
4       6789080S            640.0000000000  2017-11-16  0           2017-11-16      201746
5       6789213S            0.0000000000    2017-11-16  0           2017-11-16      201746
6       6789098S            0.0000000000    2017-11-15  0           2017-11-15      NULL
7       6789103S            0.0000000000    2017-11-15  0           2017-11-15      NULL
8       6789110S            0.0000000000    2017-11-15  0           2017-11-15      NULL
9       6789751S            250.0000000000  2017-11-13  0           2017-11-13      NULL
10      6789756S            250.0000000000  2017-11-13  0           2017-11-13      NULL
11      6789773S            25.0000000000   2017-11-13  0           2017-11-13      NULL
12      6789779S            242.0000000000  2017-11-14  0           2017-11-14      201746
13      6789816S            23.8800000000   2017-11-14  0           2017-11-14      201746
14      6789833S            190.0000000000  2017-11-14  0           2017-11-14      201746
15      6789845S            215.0000000000  2017-11-14  0           2017-11-14      201746    

修改

我的原始答案错过了OP的一些重要细节。这是一个完全重写的答案。

答案 2 :(得分:0)

这将在你想要的结果中提到: -

select mastr.* , case when mastr.deliverydate = del.deliverydate then  (CONVERT(VARCHAR(4),LEFT(mastr.DELIVERYDATE,4))  + '' + CONVERT(VARCHAR(4),DATEPART( wk, mastr.DELIVERYDATE)))  else null end as 'WeekOfYear' from
    [dbo].[CurrentOrder] mastr 
    left join 
        (Select distinct deliverydate from 
            (select deliverydate, rank() over(partition by deliverydate order by orderid) as cnt 
            from [dbo].[CurrentOrder] where [CANCELLED] = 0) ranked
        Where cnt > 3) del
    on mastr.deliverydate = del.deliverydate