返回所有已连续两个订单订购肯德基的客户

时间:2019-12-09 09:00:03

标签: sql sql-server

我试图找出哪些顾客在一家餐厅连续2次下订单。我正在使用两个表Orders和Order_rank。

Order_rank包含客户成功订单的计数-例如如果订单编号的订单等级为2,则该订单是该客户自注册以来的第二次连续订单。

订单:

DataTable dt = new DataTable();
        string Secteur, Reference, Title, DateLimite, DatePublication, Lieux;
        dt.Columns.Add("Secteur", typeof(string));
        dt.Columns.Add("Reference", typeof(string));
        dt.Columns.Add("Title", typeof(string));
        dt.Columns.Add("DateLimite", typeof(string));
        dt.Columns.Add("DatePublication", typeof(string));
        dt.Columns.Add("Lieux", typeof(string));

        try
        {
            using (SPSite site = new SPSite(SPContext.Current.Site.Url))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    SPList list = web.Lists["Offres"];


                    SPListItemCollection coll = list.Items;
                    foreach (SPListItem item in coll)
                    {
                        if (item["Secteur"] != null)
                        {
                            Secteur = item["Secteur"].ToString();
                        }
                        else
                        {
                            Secteur = "";
                        }


                        if (item["Reference"] != null)
                            Reference = item["Reference"].ToString();
                        else
                            Reference = " ";

                        if (item["Title"] != null)
                            Title = item["Title"].ToString();
                        else
                            Title = " ";

                        if (item["DateLimite"] != null)
                            DateLimite = item["DateLimite"].ToString();
                        else
                            DateLimite = " ";

                        if (item["DatePublication"] != null)
                            DatePublication = item["DatePublication"].ToString();
                        else
                            DatePublication = " ";

                        if (item["Lieux"] != null)
                            Lieux = item["Lieux"].ToString();
                        else
                            Lieux = " ";


                        dt.Rows.Add(Secteur, Reference, Title, DateLimite, 
                          DatePublication, Lieux);
                    }
                    OffresGrid.DataSource = dt;
                    OffresGrid.DataBind();
                }
            }
        }
        catch (Exception )
        {
        }

Order_rank:

Createdate | Orderid  | OrderStatus | Customerid | Restaurantname
---------- | -------  | ----------- | ---------- | --------------
2019-08-03 | 1338     | Accepted    | 45         | KFC            
2019-08-04 | 3266     | Accepted    | 45         | KFC
2019-08-06 | 1595     | Null        | 37         | Burger King 
2019-08-07 | 9258     | Null        | 89         | KFC
2019-08-12 | 4853     | Accepted    | 22         | Burger King
2019-08-13 | 5682     | Null        | 22         | Burger King
2019-08-14 | 3515     | Accepted    | 16         | Burger King
2019-08-16 | 2495     | Accepted    | 16         | KFC
2019-08-22 | 2359     | Accepted    | 35         | KFC
2019-08-25 | 2456     | Null        | 47         | Burger King

我要显示的输出是这样的:

Customerid | Orderid | Rank
---------- | ------- | ----
16         | 2495    | 2
16         | 3515    | 2 
22         | 4853    | 3
22         | 5682    | 1
35         | 2359    | 1
37         | 1595    | 1
45         | 1338    | 2
45         | 3266    | 2
47         | 2456    | 3

我需要显示两个连续订单的订单日期。

我该如何实现?

这是我尝试过的方法,但是并没有达到我想要的效果:

Customerid | Createdate | Orderid | RestaurantName
---------- | ---------- | ------- | --------------
45         | 2019-08-03 | 1338    | KFC
45         | 2019-08-04 | 3266    | KFC

4 个答案:

答案 0 :(得分:0)

如果您只想在order_rank表中显示排名为2的订单,我想,您需要做的就是将Order表通过Orderid连接到Order_rank并为Rank = 2放置WHERE语句,如果您也想考虑等级为3或更高的等级,只需更改为Rank> = 2。

SELECT Orders.Customerid,
    Orders.Createdate,
    Orders.Orderid,
   Orders.Restaurantname
FROM Orders LEFT OUTER JOIN Order_rank ON (Orders.Orderid=Order_rank.Orderid)
WHERE Order_rank.Rank=2;

答案 1 :(得分:0)

如果我理解正确,那么我会将其视为“缺口和岛屿问题”,并执行以下操作:

USE Sandbox;
GO
/*
Createdate | Orderid  | OrderStatus | Customerid | Restaurantname
---------- | -------  | ----------- | ---------- | --------------
2019-08-03 | 1338     | Accepted    | 45         | KFC            
2019-08-04 | 3266     | Accepted    | 45         | KFC
2019-08-06 | 1595     | Null        | 37         | Burger King 
2019-08-07 | 9258     | Null        | 89         | KFC
2019-08-12 | 4853     | Accepted    | 22         | Burger King
2019-08-13 | 5682     | Null        | 22         | Burger King
2019-08-14 | 3515     | Accepted    | 16         | Burger King
2019-08-16 | 2495     | Accepted    | 16         | KFC
2019-08-22 | 2359     | Accepted    | 35         | KFC
2019-08-25 | 2456     | Null        | 47         | Burger King
*/
--Sample Data
WITH VTE AS(
    SELECT CONVERT(date,V.Createdate) AS Createdate,
           V.Orderid,
           NULLIF(RTRIM(V.OrderStatus),'null') AS OrderStatus,
           V.Customerid,
           RTRIM(V.Restaurantname) AS Restaurantname
    FROM (VALUES('2019-08-03',1338,'Accepted',45,'KFC        '),    
                ('2019-08-04',3266,'Accepted',45,'KFC        '),
                ('2019-08-06',1595,'Null    ',37,'Burger King'), 
                ('2019-08-07',9258,'Null    ',89,'KFC        '),
                ('2019-08-12',4853,'Accepted',22,'Burger King'),
                ('2019-08-13',5682,'Null    ',22,'Burger King'),
                ('2019-08-14',3515,'Accepted',16,'Burger King'),
                ('2019-08-16',2495,'Accepted',16,'KFC        '),
                ('2019-08-22',2359,'Accepted',35,'KFC        '),
                ('2019-08-25',2456,'Null    ',47,'Burger King'))V(Createdate,Orderid,OrderStatus,Customerid,Restaurantname)),
--Solution
Grps AS(
    SELECT V.Createdate,
           V.Orderid,
           V.OrderStatus,
           V.Customerid,
           V.Restaurantname,
           ROW_NUMBER() OVER (PARTITION BY V.Customerid  ORDER BY V.Orderid) - 
           ROW_NUMBER() OVER (PARTITION BY V.Customerid,V.Restaurantname ORDER BY V.Orderid) AS Grp
    FROM VTE V),
Counts AS(
    SELECT G.Createdate,
           G.Orderid,
           G.OrderStatus,
           G.Customerid,
           G.Restaurantname,
           G.Grp,
           COUNT(*) OVER (PARTITION BY G.Customerid,G.Grp) AS ConsecOrders
    FROM Grps G)
SELECT C.Createdate,
       C.Orderid,
       C.OrderStatus,
       C.Customerid,
       C.Restaurantname
FROM Counts C
WHERE C.ConsecOrders > 1;

请注意,我在上面的结果集中得到了4行:

Createdate Orderid     OrderStatus Customerid  Restaurantname
---------- ----------- ----------- ----------- --------------
2019-08-12 4853        Accepted    22          Burger King
2019-08-13 5682        NULL        22          Burger King
2019-08-03 1338        Accepted    45          KFC
2019-08-04 3266        Accepted    45          KFC

我认为这是预料之中的,因为客户22连续从汉堡王那里定购了订单(只是其中的一项不被接受)。如果您只想接受已接受的订单,则应该很容易就能算出在何处添加适当的WHERE

答案 2 :(得分:0)

我认为您可能想在Orders_rank上尝试DENSE_RANK(),因为与RANK()不同,DENSE_RANK()返回连续的排名值。

SELECT
           o.*
FROM       dbo.Orders       AS o
INNER JOIN (SELECT
                  Customerid
                , Orderid
                , DENSE_RANK() OVER (PARTITION BY Rank ORDER BY Customerid) AS Consec
            FROM  dbo.Orders_Rank
            WHERE Rank = 2) AS r ON o.Customerid = r.Customerid
                                    AND o.Orderid = r.Orderid
                                    AND r.Consec = 2
WHERE      o.OrderStatus = 'Accepted'
           AND o.Restaurantname = 'KFC';

一如既往,可能会有更优雅的方法来解决此问题,但类似的事情应该可以解决。

答案 3 :(得分:0)

使用可以使用lag()lead()

select o.*   -- whatever columns you want
from (select o.*, orr.customerid,
             lag(o.restaurant) over (partition by o.customerid order by createddate) as prev_restaurant,
             lead(o.restaurant) over (partition by o.customerid order by createddate) as next_restaurant
      from orders o 
     ) o
where restaurant = 'KFC' and
      restaurant in (prev_restaurant, next_restaurant);

除非您出于过滤目的需要使用order_rank,否则我在查询中看不到任何用处。