请教一个sql(按2个字段分组然后从每组取出最大的一条纪录,再根据一个标记为判断是不是取出该值)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请教一个sql(按2个字段分组然后从每组取出最大的一条纪录,再根据一个标记为判断是不是取出该值)相关的知识,希望对你有一定的参考价值。

比如:比如表 test
字段有:id、number、dept、 date、 flag
1 001 aa 20130201 1
2 001 aa 20120801 0
3 001 bb 20130403 1
4 001 bb 20120404 0
5 001 cc 20120604 0
首先,我需要根据number、dept2个字段来分组,等到如下结果:
id、number、dept、 date、 flag
1 001 aa 20130201 1
3 001 bb 20130403 1
5 001 cc 20120604 0
然后,我以number为纬度,判断flag是否全为1,如果为全为1,则取出最大的时间date,
如果不全为1,则不需要取出时间,给0就行;就拿上面的例子来说,在分组之后falg不全为1了,
则不需要取出时间了,假设全为1,则需要取出最大时间20130403。
求各位帮忙,谢谢!

参考技术A CREATE TABLE #test (
  id INT,
  [number]  varchar(6),
  dept  varchar(6),
  [date]  int,
  flag  int
);
GO

INSERT INTO #test
SELECT 1, '001',  'aa',  20130201,  1   UNION ALL
SELECT 2, '001',  'aa',  20120801,  0   UNION ALL
SELECT 3, '001',  'bb',  20130403,  1   UNION ALL
SELECT 4, '001',  'bb',  20120404,  0   UNION ALL
SELECT 5, '001',  'cc',  20120604,  0   UNION ALL
SELECT 6, '002',  'aa',  20130201,  1   UNION ALL
SELECT 7, '002',  'aa',  20120801,  0   UNION ALL
SELECT 8, '002',  'bb',  20130403,  1   UNION ALL
SELECT 9, '002',  'bb',  20120404,  0   UNION ALL
SELECT 10,'002',  'cc',  20120604,  1
GO



SELECT
  main.*
FROM
  #test main
WHERE
  NOT EXISTS (
    SELECT 1 
FROM #test sub 
WHERE main.[number] = sub.[number]  AND  main.[dept] = sub.[dept] AND main.[id] > sub.[id]
  );
GO

id          number dept   date        flag
----------- ------ ------ ----------- -----------
          1 001    aa        20130201           1
          3 001    bb        20130403           1
          5 001    cc        20120604           0
          6 002    aa        20130201           1
          8 002    bb        20130403           1
         10 002    cc        20120604           1

(6 行受影响)


With MyCTE AS(
SELECT
  main.*
FROM
  #test main
WHERE
  NOT EXISTS (
    SELECT 1 
FROM #test sub 
WHERE main.[number] = sub.[number]  AND  main.[dept] = sub.[dept] AND main.[id] > sub.[id]
  )
)
SELECT
  [number] ,  MAX([date]) AS date
FROM
  MyCTE
GROUP BY
  [number]
HAVING
  SUM( CASE WHEN flag = 1 THEN 1 ELSE 0 END ) = COUNT(flag);
GO

number date
------ -----------
002       20130403

(1 行受影响)

追问

你好,非常感谢你,再请教下,第一个查询
NOT EXISTS ---------------把这个not去掉

main.[id] > sub.[id]-----------------把这个删除掉

这样应该不会出错吧

另外,我需要最后需要返回多一列,就是flag 1或者0;
把不全为1的时间返回0或者null,然后把这些合成一张表,
该如何实现呢,谢谢!
如果在的话,可以现在答复我!

追答

你这个需求变化得真是快啊。


NOT EXISTS      ---------------把这个not去掉
main.[id] > sub.[id]-----------------把这个删除掉
这样应该不会出错吧


语法不会抱错, 就是结果会发生变化了, 因为逻辑变化了。

SELECT
  main.*
FROM
  #test main
WHERE
  EXISTS (
    SELECT 1 
    FROM #test sub 
    WHERE main.[number] = sub.[number]  AND  main.[dept] = sub.[dept] 
  );
GO

id          number dept   date        flag
----------- ------ ------ ----------- -----------
          1 001    aa        20130201           1
字数限制,这里就省略部分。
         10 002    cc        20120604           1

(10 行受影响)



这样一来, 下面那个查询。 对于每一个 number,  因为  flag 都有 0 了。

那么结果一行也没有了。




至于你需要最后需要返回多一列,就是flag 1或者0;

把不全为1的时间返回0或者null

With MyCTE AS(
  第一步的子查询写在这个位置.
)
SELECT
  [number] ,    MAX([date]) AS date,   1  AS  flag
FROM
  MyCTE
GROUP BY
  [number]
HAVING
  SUM( CASE WHEN flag = 1 THEN 1 ELSE 0 END ) = COUNT(flag)
-- 上面是flag全部为1的
UNION  ALL
-- 下面是flag不全部为1的
SELECT
  [number] ,    0 AS date,   0  AS  flag
FROM
  MyCTE
GROUP BY
  [number]
HAVING
  SUM( CASE WHEN flag = 1 THEN 1 ELSE 0 END ) < COUNT(flag)

本回答被提问者采纳
参考技术B SELECT NUMBER,
DEPT,
CASE
WHEN S.B = S.C AND S.B = 1 THEN
S.A
ELSE
0
END
FROM (SELECT NUMBER, DEPT, MAX(DATE) A, MIN(FLAG) B, MAX(FLAG) C
FROM TEST T
GROUP BY NUMBER, DEPT) S;
id是没有意义的
参考技术C

---sqlserver语法

SELECT A.* INTO #TEMPTABLE FROM test A ,
(SELECT NUMBER ,DEPT,MAX(DATE) AS MAXDATE FROM  test GROUP BY NUMBER ,DEPT) B WHERE A.NUMBER=B.NUMBER AND A.DEPT=B.DEPT AND A.DATE=B.MAXDATE
IF EXISTS (SELECT 1 FROM #TEMPTABLE WHERE FLAG=0)
BEGIN
SELECT 0
END
IF NOT EXISTS (SELECT 1 FROM #TEMPTABLE WHERE FLAG=0)
BEGIN
SELECT MAX(DATE) FROM #TEMPTABLE
END

MYSQL基础

 

1.having和group by的区别?

1.having:用于对where和group by查询出来的分组经行过滤,查出满足条件的分组结果。它是一个过滤声明,是在查询返回结果集以后对查询结果进行的过滤操作。

2.group by:对select查询出来的结果集按照某个字段或者表达式进行分组,获得一组组的集合,然后从每组中取出一个指定字段或者表达式的值。 在说group by的时候,我们还需要了解聚合函数,聚合函数是SQL语言中一种特殊的函数。

 关于聚合索引、group by与having的使用:https://blog.csdn.net/intmainhhh/article/details/80777582

技术图片

 

扩展资料:

group by,where,having 是数据库查询中最常用的几个关键字。在工作中,时常用到,当一个语句中同时含有where、group by 、having及聚集函数时,执行顺序如下:

执行where子句查找符合条件的数据;使用group by 子句对数据进行分组;对group by 子句形成的组运行聚集函数计算每一组的值;最后用having 子句去掉不符合条件的组。需要注意的是,having 子句中的每一个元素也必须出现在select列表中。有些数据库例外,如oracle。

---恢复内容结束---

以上是关于请教一个sql(按2个字段分组然后从每组取出最大的一条纪录,再根据一个标记为判断是不是取出该值)的主要内容,如果未能解决你的问题,请参考以下文章

mysql分组后,取每组的前3条数据(并且有顺序)

oracle开展分组后,取出每组的前几条数据

sql按字段分组,排序,并且找出每组最大的数据

sql取出每个分组的前几条

sql数据库怎么实现分组并取每组的前1条语句,按日期排序?

having和group by的区别?