SQL如何让SQL为每个不同的ID返回一行而不是多行?

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

据我的同事说,我们正在使用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-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