SQL 按 GROUP 查询当前行和上一行之间的差异
SQL Query for difference between current and previous row by GROUP
我是 SQL 的新手。我有以下 table 结构。对于给定的 SITEID 和给定的 YEAR,我试图找到添加的 "new" CLASS,即前一年不存在的 CLASS。每个站点可以有多个 类。
<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>
非常感谢您的帮助。谢谢。
SELECT SITEID, YEAR, max(CLASS) AS CLASS FROM [dbo].[TestTable] GROUP BY YEAR,SITEID
您可以使用 window 函数:
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
这将 return "A" 和 "B" 用于 2007 年。虽然这不是您提供的结果,但您的问题似乎是要问的。
请试试这个(请将 temp table 替换为您的 table):
如果您使用的是 SQL 服务器,那么您可以使用通用 Table 表达式 (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 服务器),那么您可以使用连接(可能需要针对正在使用的 RDBMS 调整查询) 如下:
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;
我的SQLFiddlehere (http://sqlfiddle.com/#!9/c570d57/1/0)
我是 SQL 的新手。我有以下 table 结构。对于给定的 SITEID 和给定的 YEAR,我试图找到添加的 "new" CLASS,即前一年不存在的 CLASS。每个站点可以有多个 类。
<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>
非常感谢您的帮助。谢谢。
SELECT SITEID, YEAR, max(CLASS) AS CLASS FROM [dbo].[TestTable] GROUP BY YEAR,SITEID
您可以使用 window 函数:
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
这将 return "A" 和 "B" 用于 2007 年。虽然这不是您提供的结果,但您的问题似乎是要问的。
请试试这个(请将 temp table 替换为您的 table):
如果您使用的是 SQL 服务器,那么您可以使用通用 Table 表达式 (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 服务器),那么您可以使用连接(可能需要针对正在使用的 RDBMS 调整查询) 如下:
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;
我的SQLFiddlehere (http://sqlfiddle.com/#!9/c570d57/1/0)