如何显示与产品相关的价格逐年上升

时间:2019-05-04 16:24:19

标签: sql-server sql-server-2012

我对SQL Server有一个疑问。如何获得哪个产品名称的价格逐年上涨。 下表中的苹果产品价格逐年增加,因此我需要该记录 如果某产品一年的价格高而另一年的价格下降,则无需获取该记录 如果任何产品的一年价格为10,而下一年的价格必须比上一个价格高,则该记录需要显示

CREATE TABLE [dbo].[product](
    [pid] [int] NULL,
    [price] [money] NULL,
    [year] [int] NULL
);

CREATE TABLE [dbo].[productdetails](
    [pid] [int] NULL,
    [pname] [varchar](50) NULL
);

INSERT [dbo].[product] ([pid], [price], [year]) VALUES (1, 10.0000, 2010);
INSERT [dbo].[product] ([pid], [price], [year]) VALUES (1, 9.0000, 2011);
INSERT [dbo].[product] ([pid], [price], [year]) VALUES (1, 13.0000, 2012);
INSERT [dbo].[product] ([pid], [price], [year]) VALUES (2, 30.0000, 2010);
INSERT [dbo].[product] ([pid], [price], [year]) VALUES (2, 20.0000, 2011);
INSERT [dbo].[product] ([pid], [price], [year]) VALUES (2, 19.0000, 2012);
INSERT [dbo].[product] ([pid], [price], [year]) VALUES (3, 8.0000, 2010);
INSERT [dbo].[product] ([pid], [price], [year]) VALUES (3, 10.0000, 2011);
INSERT [dbo].[product] ([pid], [price], [year]) VALUES (3, 15.0000, 2012);

INSERT [dbo].[productdetails] ([pid], [pname]) VALUES (1, N'lg');
INSERT [dbo].[productdetails] ([pid], [pname]) VALUES (2, N'samsung');
INSERT [dbo].[productdetails] ([pid], [pname]) VALUES (3, N'apple');
INSERT [dbo].[productdetails] ([pid], [pname]) VALUES (4, N'mi');

基于上面的数据,我希望输出如下

+--------------+
| Productname  |
+--------------+
| Apple        |
+--------------+

我尝试如下

SELECT *
FROM   product p
       JOIN product pd
         ON p.pid = pd.pid
            AND p.year = pd.year + 1
            AND p.price >= pd.price 

能否请您告诉我如何编写查询以在SQL Server中实现此任务

6 个答案:

答案 0 :(得分:1)

不存在:

select distinct pd.pname [Product Name]
from [dbo].[productdetails] pd inner join [dbo].[product] p
on p.pid = pd.pid
where not exists (
  select 1 from product t
  where t.pid = pd.pid and 
  t.price <= (select price from product where pid = t.pid and year = t.year - 1)
)

请参见demo
结果:

> | Product Name  |
> | :------------ |
> | apple         |

如果没有每年的价格,但您想将该条件应用于上一个存储的年份,则使用以下方法:

select distinct pd.pname [Product Name]
from [dbo].[productdetails] pd inner join [dbo].[product] p
on p.pid = pd.pid
where not exists (
  select 1 from product t
  where t.pid = pd.pid and 
  t.price <= (select max(price) from product where pid = t.pid and year < t.year)
) 

请参见demo

答案 1 :(得分:1)

使用LAG() = HAVING的{​​{1}}和COUNT,可以得到预期的结果。

查询是动态的,无需对年份或出现次数进行硬编码。

SUM

输出:

SELECT Q.pname AS ProductName
FROM (
    SELECT PD.PID, PD.pname,
          CASE WHEN COALESCE(
                      LAG(PR.price) OVER (PARTITION BY PD.PID ORDER BY PR.[year])
                   , PR.price) <= PR.price THEN 1 ELSE 0 END AS PFlag
    FROM product PR
    JOIN productdetails PD ON PD.pid = PR.pid
) Q 
GROUP BY Q.pname
HAVING COUNT(Q.pname) = SUM(Q.PFlag)

db<> fiddle for the same

答案 2 :(得分:0)

如果2010、2011和2012年的固定数据始终存在-以下脚本将起作用-

SELECT
PID
FROM [dbo].[product]
GROUP BY PID
HAVING 
SUM(CASE WHEN [YEAR] = '2011' THEN PRICE ELSE NULL END)> 
    SUM(CASE WHEN [YEAR] = '2010' THEN PRICE ELSE NULL END)
AND 
SUM(CASE WHEN [YEAR]= '2012' THEN PRICE ELSE NULL END)>
    SUM(CASE WHEN [YEAR] = '2011' THEN PRICE ELSE NULL END)

答案 3 :(得分:0)

另一种方法是 (取消注释p1和p0以查看详细信息)

SELECT Distinct
    pd.pname as Product
  --,p0.*
  --,p1.*
FROM   gbaluproduct p0
JOIN   gbaluproduct p1
   ON  p0.pid    = p1.pid
   AND p0.year + 1   = p1.year 
   AND p0.price < p1.price 
Left Join gbaluproductdetails pd
   ON  p0.pid    = pd.pid

结果-

Product
apple
lg

答案 4 :(得分:0)

您可以使用此查询...
即使您每个产品有3条数据记录,此方法也有效。

SELECT Max(productdetails.pname) as ProductName
FROM   (SELECT *,
               Lag(price, 1) OVER (partition BY pid ORDER BY pid, year ) AS LagPrice,
               price AS CurrentPrice,
               Lead (price, 1) OVER (partition BY pid ORDER BY pid, year) AS LeadPrice
        FROM   product) t1
       INNER JOIN productdetails ON productdetails.pid = t1.pid
WHERE  lagprice IS NOT NULL AND leadprice IS NOT NULL
GROUP  BY t1.pid
HAVING Max(CASE WHEN leadprice < currentprice OR lagprice > currentprice THEN 1 ELSE 0 END) < 1  

或使用此查询(类似于Arulkumar's query)。

SELECT Max(productdetails.pname) AS ProductName
FROM   (SELECT pid,
               CASE WHEN Lead(price) OVER (partition BY pid ORDER BY pid, year) >= price THEN 0 ELSE 1
               END AS Decreased
        FROM   product) tmp
       INNER JOIN productdetails ON productdetails.pid = tmp.pid
GROUP  BY tmp.pid
HAVING Sum(tmp.Decreased) <= 1  

表架构和示例数据(添加了更多示例数据)

CREATE TABLE [product](
    [pid] [int] NULL,
    [price] [money] NULL,
    [year] [int] NULL
);

CREATE TABLE [productdetails](
    [pid] [int] NULL,
    [pname] [varchar](50) NULL
);

INSERT [product] ([pid], [price], [year]) VALUES (1, 10.0000, 2010);
INSERT [product] ([pid], [price], [year]) VALUES (1, 9.0000, 2011);
INSERT [product] ([pid], [price], [year]) VALUES (1, 13.0000, 2012);
INSERT [product] ([pid], [price], [year]) VALUES (2, 30.0000, 2010);
INSERT [product] ([pid], [price], [year]) VALUES (2, 20.0000, 2011);
INSERT [product] ([pid], [price], [year]) VALUES (2, 19.0000, 2012);
INSERT [product] ([pid], [price], [year]) VALUES (3, 8.0000, 2010);
INSERT [product] ([pid], [price], [year]) VALUES (3, 10.0000, 2011);
INSERT [product] ([pid], [price], [year]) VALUES (3, 15.0000, 2012);
INSERT [product] ([pid], [price], [year]) VALUES (3, 20.0000, 2013);
INSERT [product] ([pid], [price], [year]) VALUES (3, 15.0000, 2014);
INSERT [product] ([pid], [price], [year]) VALUES (4, 5.0000, 2010);
INSERT [product] ([pid], [price], [year]) VALUES (4, 10.0000, 2011);
INSERT [product] ([pid], [price], [year]) VALUES (4, 15.0000, 2012);
INSERT [product] ([pid], [price], [year]) VALUES (4, 20.0000, 2013);

INSERT [productdetails] ([pid], [pname]) VALUES (1, N'lg');
INSERT [productdetails] ([pid], [pname]) VALUES (2, N'samsung');
INSERT [productdetails] ([pid], [pname]) VALUES (3, N'apple');
INSERT [productdetails] ([pid], [pname]) VALUES (4, N'mi');

所有数据

+------+----------+------+
| pid  |  price   | year |
+------+----------+------+
|   1  | 10.0000  | 2010 |
|   1  |  9.0000  | 2011 |
|   1  | 13.0000  | 2012 |
|   2  | 30.0000  | 2010 |
|   2  | 20.0000  | 2011 |
|   2  | 19.0000  | 2012 |
|   3  |  8.0000  | 2010 |
|   3  | 10.0000  | 2011 |
|   3  | 15.0000  | 2012 |
|   3  | 20.0000  | 2013 |
|   3  | 15.0000  | 2014 |
|   4  |  5.0000  | 2010 |
|   4  | 10.0000  | 2011 |
|   4  | 15.0000  | 2012 |
|   4  | 20.0000  | 2013 |
+------+----------+------+

查询结果

+-------------+
| ProductName |
+-------------+
| mi          |
+-------------+

在线演示:https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=c55c02790f1a6f99bb8d560ab8d3149b


参考
-Arulkumar的查询:https://stackoverflow.com/revisions/55984816/2

答案 5 :(得分:0)

如果我理解正确。您可以利用COUNT()LAG()SUM()的优势,然后将逻辑分为:

  1. 获取当前和上一年的价格
  2. 计算产品记录的总数(每个产品有多少年)。
  3. 将当前年的价格与去年的价格进行比较,如果当前年的价格大于去年的价格,则为增量(我们给它1),否则为(降低)我们给它0。
  4. 获取比较的总和,如果它等于产品总数(第二个计数),则表示该产品从未降低过价格。

示例:

 SELECT
    pname
FROM (
    SELECT 
        p.pid
    ,   p.price
    ,   p.year
    ,   LAG(p.price) OVER(PARTITION BY p.pid ORDER BY p.year) prvPrice
    ,   COUNT(*) OVER(PARTITION BY p.pid) totalPid
    ,   pd.pname
    FROM product p
    JOIN productdetails pd ON pd.pid = p.pid
) D 
GROUP BY    
    pname
,   totalPid
HAVING 
    SUM(CASE WHEN price > ISNULL(prvPrice,0) THEN 1 ELSE 0 END) = totalPid

因此,苹果在产品表(totalPid)中出现了3次,这意味着我们需要将价格提高3次(每年一次)才能满足您的要求。

您可以根据需要更正条件逻辑,但是为了简单起见,我只想分享这个简单的示例。