как отобразить, какая цена, связанная с продуктом, увеличивается с каждым годом - PullRequest
1 голос
/ 04 мая 2019

У меня есть одно сомнение в SQL-сервере. Как узнать, какое название продукта растет с каждым годом. в таблице ниже цена продукта Apple увеличивается с каждым годом, поэтому мне нужно, чтобы записи если какой-либо продукт один год является высоким, а цена другого года снижается, то нет необходимости получать эти записи если цена какого-либо продукта на один год равна 10, а цена на следующий год должна быть увеличена по сравнению с prviouse, тогда эта запись должна отображаться

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-сервере.

Ответы [ 6 ]

1 голос
/ 04 мая 2019

Используя LAG() и HAVING с 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)

ВЫХОД:

+--------------+
| Productname  |
+--------------+
| apple        |
+--------------+

дб <> скрипка для того же

1 голос
/ 04 мая 2019

С НЕ СУЩЕСТВУЮЩИМ:

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)
)

См. Демоверсию .
Результаты:

> | 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)
) 

См. Демоверсию .

0 голосов
/ 05 мая 2019

Если я правильно понял.Вы можете воспользоваться COUNT(), LAG() и SUM() и просто разделить свою логику на:

  1. Получить текущую и предыдущую цену года
  2. Подсчитать общее количествоколичество записей продукта (сколько лет существует для каждого продукта).
  3. Сравните цену текущего года с ценой прошлого года, и если цена текущего года больше, чем в прошлом году, то она увеличивается (мы даем ей 1), иначе (она уменьшается), мы даем ей 0.
  4. Получите сумму сравнения, если она равна общему количеству продуктов (счет № 2), то это означает, что продукт никогда не снижал цену.

Пример:

 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

Итак, яблоко появилось 3 раза в таблице продуктов (totalPid), это означает, что нам нужно увеличить цену в 3 раза (один раз в год), чтобы выполнитьваше требование

Вы можете исправить условную логику в соответствии со своими потребностями, но я просто хочу поделиться этим простым примером ради простоты.

0 голосов
/ 04 мая 2019

Вы можете использовать этот запрос ...
Это работает, даже если у вас есть более 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  

Или используйте этот запрос (аналогично запросу Арулкумара ).

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


Ссылка
- запрос Арулкумара: https://stackoverflow.com/revisions/55984816/2

0 голосов
/ 04 мая 2019

Другой способ (раскомментируйте 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
0 голосов
/ 04 мая 2019

Если данные всегда есть для фиксированного года 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)
...