根据我的同事的说法,我们正在使用IBM DB2
我真的很难让我的sql每个ID返回一行。在工作中被问到但是这里没有女孩对SQL很好......我可以做一些SQL但不是SQL专家。
为了更好地解释,我设置了以下示例
这是TABLE及其数据
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
工作得很好。我会得到
01 2016-08-21
02 2016-10-01
我很快意识到我还需要PERCENT专栏。
SELECT ID, MIN(DATE), PERCENT
FROM TABLE
WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01'
AND CODE = 1111
GROUP BY ID, PERCENT
但现在,我为ID 01获取了多行,这是错误的......
01 2016-08-21 1111 52
01 2016-09-06 1111 60
02 2016-10-01 1111 50
有人可以帮我修复这个SQL或者指向正确的方向,这样我每个ID就可以有一行,如下所示吗?
01 2016-08-21 1111 52
02 2016-10-01 1111 50
答案 0 :(得分:1)
GROUP BY ID将执行必要的操作,无需GROUP BY百分比。如果您是GROUP BY百分比,则会添加一个新行,因为它具有不同的值。
SELECT ID, MIN(DATE), code, percent
FROM table
WHERE DATE BETWEEN '2016-01-01' AND '2017-11-01'
AND CODE = 1111
GROUP BY ID;
希望这有帮助。
答案 1 :(得分:1)
IF 您的数据库支持row_number() over()
,然后使用该功能是确定哪些行是最早的&#34;最早的&#34;像这样:
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
这样做的显着优点是它可以访问与&#34;最老的&#34;相关的整行。无需加入。
注意这种方法的灵活性,它可以很容易地扩展,例如
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
所有人都必须做到最近的&#34;是将顺序从ASCending更改为DESCending。
注意:v8之前的MySQL不支持&#34;窗口函数,例如row_number,但是计划在v8之后。许多其他数据库都支持此功能。
答案 2 :(得分:0)
SELECT
Earliest.ID,
Earliest.Date,
TABLE.PERCENT
FROM (
SELECT
ID,
MIN(DATE)
FROM
TABLE
WHERE
DATE BETWEEN '2016-01-01' AND '2017-11-01'
AND CODE = 1111
GROUP BY ID
) AS Earliest
INNER JOIN TABLE ON Earliest.ID = Table.ID
解释为什么您的调整后的查询返回多个记录:百分比列具有不同的数据,因此当您按其分组时,它将为每个更改添加新记录。
在这个答案中,您可以通过加入汇总结果从基础表中获得百分比。
答案 3 :(得分:0)
如果这是SQL Server,您可以使用TOP 1 WITH TIES
和ORDER BY
:
SELECT TOP 1 WITH TIES ID, DATE, PERCENT
FROM TABLE
WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01'
AND CODE = 1111
ORDER BY ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DATE ASC)
答案 4 :(得分:0)
不要按PERCENT分组,只按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;
答案 5 :(得分:0)
我假设您正在使用MS SQL Server。您可以使用所谓的CTE(使用cluse)来获取最小日期,然后将其加入主表:see the working example on sql fiddle
-- first find the min date for each ID
with min_date as (
SELECT ID, MIN(DATE) [DATE]
FROM tbl
WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01'
AND CODE = 1111
GROUP BY ID
)
-- join it to the table and get the result
select t.ID, md.[DATE], t.[PERCENT]
from tbl t
inner join min_date as md
on md.ID = t.ID and md.[DATE] = t.[date]
答案 6 :(得分:0)
PERCENT击败群组的原因是因为PERCENT在行之间有所不同,而您正在使用GROUP BY 删除重复项。 PERCENT使行不同...您可以改为子查询从表中重新获取具有相同ID和MIN(DATE)的行
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