SQL如何让SQL为每个不同的ID返回一行而不是多行?
据我的同事说,我们正在使用IBMDB2 真的很难让我的sql每个ID返回一行。在工作中被询问过,但这里没有一个女孩擅长sql。。。我可以做一些sql,但不是sql专家 为了更好地解释它,我设置了下面的示例 这是表格及其数据SQL如何让SQL为每个不同的ID返回一行而不是多行?,sql,Sql,据我的同事说,我们正在使用IBMDB2 真的很难让我的sql每个ID返回一行。在工作中被询问过,但这里没有一个女孩擅长sql。。。我可以做一些sql,但不是sql专家 为了更好地解释它,我设置了下面的示例 这是表格及其数据 ID DATE CODE PERCENT 01 2016-08-21 1111 52 01 2016-09-06 1111 60 01 2016-10-06 1112 38 02 2016-05-01 6666 50 02 2016
ID DATE CODE PERCENT
01 2016-08-21 1111 52
01 2016-09-06 1111 60
01 2016-10-06 1112 38
02 2016-05-01 6666 50
02 2016-10-01 1111 50
我希望每个ID返回一条记录,其中包含最早的日期。
所以我写了下面的SQL
SELECT ID, MIN(DATE)
FROM TABLE
WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01'
AND CODE = 1111
GROUP BY ID
我很快意识到我也需要百分比列
SELECT ID, MIN(DATE), PERCENT
FROM TABLE
WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01'
AND CODE = 1111
GROUP BY ID, PERCENT
有人能帮我修复这个SQL,或者给我指出正确的方向,这样我就可以像下面这样每个ID有一行了吗
01 2016-08-21 1111 52
02 2016-10-01 1111 50
解释调整后的查询返回多条记录的原因:百分比列具有不同的数据,因此当您按其分组时,它将为该列上的每个更改添加一条新记录
在这个答案中,通过加入汇总结果,您可以从基础表中获得百分比。按ID分组将执行必要的操作,无需按百分比分组。如果按百分比分组,将添加新行,因为它具有不同的值
SELECT ID, MIN(DATE), code, percent
FROM table
WHERE DATE BETWEEN '2016-01-01' AND '2017-11-01'
AND CODE = 1111
GROUP BY ID;
希望这有帮助。如果这是SQL Server,您可以通过以下方式使用带领带的TOP 1:
不要按百分比分组,只按ID分组。在select语句中添加代码
select id, min(date), code, percent
from tablename
where date between '2016-01-01' AND '2017-11-01'
and code = 1111
group by id;
如果您的数据库支持row_number,那么使用该函数是确定哪些行最早的一种很好的方法,如下所示:
select *
from (
select *
, row_number() over(partition by ID, CODE order by DATE ASC) as is_oldest
from YOURTABLE
where DATE >= '2016-01-01' AND DATE <= '2017-11-01'
and CODE = 1111
) d
where is_oldest = 1
这样做的显著优点是,它提供了对与最早的行关联的整个行的访问,而不需要连接
请注意此方法的灵活性,它可以很容易地扩展,例如
select *
from (
select *
, row_number() over(partition by ID, CODE order by date ASC) as is_oldest
, row_number() over(partition by ID, CODE order by date DESC) as is_recent
from your_table
WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01'
AND CODE = 1111
) d
where is_oldest = 1
or is_recent = 1
要获得最新数据,只需将升序更改为降序即可
注意:v8之前的MySQL不支持诸如row_number之类的窗口功能,但计划在v8以后使用。许多其他数据库都支持此功能。百分比不支持group by的原因是行之间的百分比不同,并且您正在使用group by删除重复项。百分比使行不同。。。您可以改为使用子查询从具有相同ID和MINDATE的表中重新获取行
SELECT dT.ID
,dT.DATE
,(SELECT T.PERCENT
FROM TABLE T
WHERE T.ID = dT.ID AND T.DATE = dT.DATE
) AS Percent
FROM (
SELECT ID, MIN(DATE) AS DATE
FROM TABLE
WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01'
AND CODE = 1111
GROUP BY ID
) AS dT
这是在MS SQL Server中吗?哪个数据库管理系统???????????SQL只是一种语言。不同dbms的实现是不同的。Alison,了解您使用的数据库类型非常重要,例如MySQL Oracle、Postgres、SQL Server。。。因为解决方案将取决于数据库支持什么。SQL本身不够详细。此代码不符合ANSI SQL,但将在Sybase ASE和MySQL上运行。他们接受select而不使用GROUPBY子句。这将破坏几乎所有的dbms。
select id, min(date), code, percent
from tablename
where date between '2016-01-01' AND '2017-11-01'
and code = 1111
group by id;
select *
from (
select *
, row_number() over(partition by ID, CODE order by DATE ASC) as is_oldest
from YOURTABLE
where DATE >= '2016-01-01' AND DATE <= '2017-11-01'
and CODE = 1111
) d
where is_oldest = 1
select *
from (
select *
, row_number() over(partition by ID, CODE order by date ASC) as is_oldest
, row_number() over(partition by ID, CODE order by date DESC) as is_recent
from your_table
WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01'
AND CODE = 1111
) d
where is_oldest = 1
or is_recent = 1
SELECT dT.ID
,dT.DATE
,(SELECT T.PERCENT
FROM TABLE T
WHERE T.ID = dT.ID AND T.DATE = dT.DATE
) AS Percent
FROM (
SELECT ID, MIN(DATE) AS DATE
FROM TABLE
WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01'
AND CODE = 1111
GROUP BY ID
) AS dT