我有一个包含交易的表格,其中的列为id
,created_at
和company_id
。我想对每家公司的四个第一笔交易进行分组,并在每一行上返回每笔交易的created_at值。
换句话说,我希望我的输出的每一行对应于每个公司的四个第一笔交易(因此按company_id
分组),其中的列显示company_id
和每个的created_at这四笔交易。
我该怎么做?
示例数据:
id | company_id | created_at
---------------------------------
1123 | abcd | 10/12/2015
8291 | abcd | 10/14/2015
9012 | abcd | 10/15/2015
9540 | abcd | 10/16/2015
10342 | abcd | 10/21/2015
10456 | abcd | 10/22/2015
2301 | efgh | 10/13/2015
4000 | efgh | 11/01/2015
4023 | efgh | 11/03/2015
6239 | efgh | 11/08/2015
7500 | efgh | 11/14/2015
示例输出:
company_id | created_at_1 | created_at_2 | created_at_3 | created_at_4
--------------------------------------------------------------------------
abcd | 10/12/2015 | 10/14/2015 | 10/15/2015 | 10/16/2015
efgh | 10/13/2015 | 11/01/2015 | 11/03/2015 | 11/08/2015
答案 0 :(得分:1)
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,company_id VARCHAR(12) NOT NULL
,created_at DATE NOT NULL
);
INSERT INTO my_table VALUES
( 1123,'abcd','2015/10/12'),
( 8291,'abcd','2015/10/14'),
( 9012,'abcd','2015/10/15'),
( 9540,'abcd','2015/10/16'),
(10342,'abcd','2015/10/21'),
(10456,'abcd','2015/10/22'),
( 2301,'efgh','2015/10/13'),
( 4000,'efgh','2015/11/01'),
( 4023,'efgh','2015/11/03'),
( 6239,'efgh','2015/11/08'),
( 7500,'efgh','2015/11/14');
SELECT x.*
FROM my_table x
JOIN my_table y
ON y.company_id = x.company_id
AND y.created_at <= x.created_at
GROUP
BY x.id
HAVING COUNT(*) <= 4
ORDER
BY company_id
, created_at;
+------+------------+------------+
| id | company_id | created_at |
+------+------------+------------+
| 1123 | abcd | 2015-10-12 |
| 8291 | abcd | 2015-10-14 |
| 9012 | abcd | 2015-10-15 |
| 9540 | abcd | 2015-10-16 |
| 2301 | efgh | 2015-10-13 |
| 4000 | efgh | 2015-11-01 |
| 4023 | efgh | 2015-11-03 |
| 6239 | efgh | 2015-11-08 |
+------+------------+------------+
带变量的解决方案会快几个数量级,例如......
SELECT a.id
, a.company_id
, a.created_at
FROM
( SELECT x.*
, CASE WHEN @prev = x.company_id THEN @i:=@i+1 ELSE @i:=1 END i, @prev:=x.company_id prev
FROM my_table x
, (SELECT @i:=1,@prev:=null) vars
ORDER
BY x.company_id
, x.created_at
) a
WHERE i <= 4;
答案 1 :(得分:0)
一种可能的方法如下:
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<!-- Servlets -->
<servlet>
<servlet-name>greetServlet</servlet-name>
<servlet-class>ch.cern.atlas.emergency.status.server.GreetingServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>greetServlet</servlet-name>
<url-pattern>/atlas_emergency_status_page/greet</url-pattern>
</servlet-mapping>
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>ATLAS_Emergency_Status_Page.html</welcome-file>
</welcome-file-list>
<!-- Servlets -->
<servlet>
<servlet-name>LoginService</servlet-name>
<servlet-class>ch.cern.atlas.emergency.status.server.LoginServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginService</servlet-name>
<url-pattern>/atlas_emergency_status_page/LoginService</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>DBService</servlet-name>
<servlet-class>ch.cern.atlas.emergency.status.server.DBServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DBService</servlet-name>
<url-pattern>/atlas_emergency_status_page/DBService</url-pattern>
</servlet-mapping>
</web-app>
编辑:
另一种可能性(受this answer启发)是:
select company_id,
min(created_at) as created_at_1,
(select created_at from t where company_id=t1.company_id order by created_at limit 1 offset 1) as created_at_2,
(select created_at from t where company_id=t1.company_id order by created_at limit 1 offset 2) as created_at_3,
(select created_at from t where company_id=t1.company_id order by created_at limit 1 offset 3) as created_at_4
from t as t1
group by company_id
答案 2 :(得分:-1)
可能这样吗?
SELECT S.company_id,
A.created_at created_at_1,
B.created_at created_at_2,
C.created_at created_at_3,
D.created_at created_at_4
FROM sample S
LEFT JOIN sample A on S.company_id = A.company_id AND A.id NOT IN(S.id)
LEFT JOIN sample B on S.company_id = B.company_id AND B.id NOT IN(S.id, A.id)
LEFT JOIN sample C on S.company_id = C.company_id AND C.id NOT IN(S.id, A.id, B.id)
LEFT JOIN sample D on S.company_id = D.company_id AND D.id NOT IN(S.id, A.id, B.id, C.id)
GROUP BY S.company_id
http://sqlfiddle.com/#!9/c577e/3
但是,它可能效率不高。它们不合适,因为你的美国日期格式不适合排序。最好切换到TIMESTAMP格式。