SQL Запрос на разницу между текущей и предыдущей строкой по GROUP - PullRequest
0 голосов
/ 09 января 2020

Я довольно новичок в SQL. У меня есть следующая структура таблицы. Для данного SITEID и данного ГОДА я пытаюсь найти «новый» КЛАСС, который был добавлен, т.е. КЛАСС, которого не было в предыдущем году. Каждый сайт может иметь несколько классов.

<table><tbody><tr><th>SITEID</th><th>YEAR</th><th>CLASS</th></tr><tr><td>1</td><td>2007</td><td>A</td></tr><tr><td>1</td><td>2007</td><td>B</td></tr><tr><td>1</td><td>2008</td><td>A</td></tr><tr><td>1</td><td>2008</td><td>B</td></tr><tr><td>1</td><td>2008</td><td>C</td></tr></tbody></table>

В вышеприведенном случае конечный вывод, который я ищу:

<table><tbody><tr><th>SITEID</th><th>YEAR</th><th>CLASS</th></tr><tr><td>1</td><td>2007</td><td> </td></tr><tr><td>1</td><td>2008</td><td>C</td></tr></tbody></table>

Буду очень признателен за вашу помощь. Спасибо.

Ответы [ 3 ]

0 голосов
/ 09 января 2020

Вы можете использовать оконные функции:

select t.*
from (select t.*, lag(year) over (partition by siteid, class order by year) as prev_year
      from t
     ) t
where prev_year is null or prev_year <> year - 1

Это вернет "A" и "B" за 2007 год. Это то, о чем спрашивает ваш вопрос, хотя это не те результаты, которые вы предоставляете.

0 голосов
/ 10 января 2020

Пожалуйста, попробуйте это (пожалуйста, замените временную таблицу своей таблицей):

Если вы используете SQL сервер, то вы можете использовать Common Table Expressions (CTE) в качестве удара:

 IF (OBJECT_ID('tempdb..#temp_table') IS NOT NULL)
    BEGIN
      DROP TABLE #temp_table
    END;

CREATE TABLE #temp_table (SiteId INT NOT NULL, [year] INT, [class] [Char] NOT NULL)

INSERT INTO #temp_table (SiteId, [year], [class])
       values 
(1, 2007,   'A'),
(1, 2007,   'B'),
(1, 2008,   'A'),
(1, 2008,   'B'),
(1, 2008,   'C')


;with temp_cte as
  (SELECT  siteid, [year], [year]-1 as [yearbefore]
            ,STUFF((SELECT '|' + CAST([class] AS VARCHAR(MAX)) [text()]
            FROM #temp_table 
            WHERE SiteId = t.SiteId and [year] = t.[year]
            FOR XML PATH(''), TYPE)
            .value('.','NVARCHAR(MAX)'),1,2,' ') [class_list]
            FROM #temp_table t
            GROUP BY SiteId, [year]
)
select c.SiteId
       , c.[year]
       , case when t.yearbefore = null then null else right(REPLACE(c.class_list, t.class_list, ''), LEN(REPLACE(c.class_list, t.class_list, ''))-1) end as [class_added]
       , case when t.yearbefore = null then null else stuff(REPLACE(c.class_list, t.class_list, ''), 1, charindex('|', REPLACE(c.class_list, t.class_list, '')), '') end as [class_added_using_stuff]
 from temp_cte c
left join temp_cte t on c.[yearbefore] = t.[year]

Если вы не используете сервер SQL (ниже также работает на сервере SQL), то вы можете использовать объединения (вероятно, необходимо настроить запросы, относящиеся к используемой СУБД), как показано ниже:

select distinct t1.SiteId, t1.[year]
    , case when t1.[year] = m.[year] then null else t1.[class] end as class_added
    from #temp_table t1
    left join #temp_table t2 on t1.SiteId = t2.SiteId and t1.class = t2.class and t1.[year] -1 = t2.[year]
    left join (select top 1 * from #temp_table order by [year] ) m on t1.[year] = m.[year]
where t2.SiteId is null

ОБНОВЛЕНИЕ для MYSQL:

CREATE TABLE test_table(
    SiteId INT NOT NULL,
    year INT,
    class CHAR(1)
);

INSERT INTO 
    test_table(SiteId, year, class)
VALUES
    (1, 2007,   'A'),
    (1, 2007,   'B'),
    (1, 2008,   'A'),
    (1, 2008,   'B'),
    (1, 2008,   'C');
select distinct t1.SiteId, t1.year
    , case when t1.year = m.year then null else t1.class end as class_added
    from test_table t1
    left join test_table t2 on t1.SiteId = t2.SiteId and t1.class = t2.class and t1.year -1 = t2.year
    left join (select * from test_table order by year limit 1) m on t1.year = m.year
where t2.SiteId is null;

МОЙ SQL Скрипка здесь (http://sqlfiddle.com/#! 9 / c570d57 / 1/0 )

0 голосов
/ 09 января 2020
SELECT SITEID, YEAR, max(CLASS) AS CLASS FROM [dbo].[TestTable] GROUP BY YEAR,SITEID

enter image description here

...