SQLite:转置 GROUP BY 的结果并用名称填充 ID
SQLite: Transposing results of a GROUP BY and filling in IDs with names
我的问题比较具体,如果你有更好的标题请推荐一个。此外,格式很糟糕 - 不知道如何组合列表和代码块。
我有一个 SQLite3 数据库,其中包含以下(的相关部分).schema:
CREATE TABLE users (id INTEGER PRIMARY KEY NOT NULL, user TEXT UNIQUE);
CREATE TABLE locations (id INTEGER PRIMARY KEY NOT NULL, name TEXT UNIQUE);
CREATE TABLE purchases (location_id INTEGER, user_id INTEGER);
CREATE TABLE sales (location_id integer, user_id INTEGER);
purchases
有大约 450 万个条目,users
大约 300k,sales
大约 100k,locations
大约 250 - 只是为了衡量数据量。
我想要的用途是生成一个 JSON object 以传递给另一个应用程序,通过执行以下操作在数量上非常压缩:
-通过 location_id、user_id 将购买和销售分组为一个共同的 table - IOW,获取每个用户每个位置的 "actions" 数量。我能做到,结果类似于
loc | usid | loccount
-----------------------
1 | 1246 | 123
1 | 2345 | 1
13 | 1246 | 46
13 | 8732 | 4
27 | 2345 | 41
(至少看起来不错,这样的体积总是很难分辨;查询:
select location_id,user_id,count(location_id) from
(select location_id,user_id from purchases
union all
select location_id,user_id from sales)
group by location_id,user_id order by user_id`
)
-然后,转置那个巨人 table 这样我会得到:
usid | loc1 | loc13 | loc27
---------------------------
1246 | 123 | 46 | 0
2345 | 1 | 0 | 41
8732 | 0 | 4 | 0
我做不到,这是我对这个问题的绝对关键点。我尝试了一些我在网上找到的东西,尤其是在这里,但我刚刚开始使用 SQLite 并且不了解很多查询。
-最后,将table翻译成纯文本,以便写入JSON:
user | AAAA | BBBBB | CCCCC
---------------------------
zeta | 123 | 46 | 0
beta | 1 | 0 | 41
iota | 0 | 4 | 0
我 可能 可以做很多实验和内部连接,尽管我总是不确定处理此类数据量的最佳方法是什么,因此我不介意一个指针。
整个事情都写在Python的sqlite3接口中,如果重要的话。最后,我希望有一些东西我可以为每个用户做一个 "for" 循环以生成 JSON,这当然会非常简单。如果查询需要很长时间(<10 分钟就好了)也没关系,它只是每天 运行 两次作为一种备份。我只有一个很小的 VPS 可用,但仅限于单核,性能与我相当强大的台式机一样好。 (i5-3570k 运行宁 Debian。)
table headers 只是示例,因为我不太确定我是否可以为它们使用整数(如果可以,我没有发现语法),只要我是以某种方式能够在 table 位置查找数字部分我很好。将用户 ID 转换为名称也是如此。列数是事先已知的——它们毕竟只是 INTEGER PRIMARY KEY,我从其他操作中得到了 list()
个。行数可以相当快地确定,大约 3 秒,如果需要的话。
考虑使用子查询来实现您想要的转置输出:
SELECT DISTINCT m.usid,
IFNULL((SELECT t1.loccount FROM tablename t1
WHERE t1.usid = m.usid AND t1.loc=1),0) AS Loc1,
IFNULL((SELECT t2.loccount FROM tablename t2
WHERE t2.usid = m.usid AND t2.loc=13),0) AS Loc13,
IFNULL((SELECT t3.loccount FROM tablename t3
WHERE t3.usid = m.usid AND t3.loc=27),0) AS Loc27
FROM tablename As m
或者,您可以使用嵌套的 IF
语句(或者在使用 CASE/WHEN
的 SQLite 的情况下)派生 table:
SELECT temp.usid, Max(temp.loc1) As Loc1,
Max(temp.loc13) As Loc13, Max(temp.loc27) As Loc27
FROM
(SELECT tablename.usid,
CASE WHEN loc=1 THEN loccount ELSE 0 As Loc1 END,
CASE WHEN loc=13 THEN loccount ELSE 0 As Loc13 END,
CASE WHEN loc=27 THEN loccount ELSE 0 As Loc27 END
FROM tablename) AS temp
GROUP BY temp.usid
我的问题比较具体,如果你有更好的标题请推荐一个。此外,格式很糟糕 - 不知道如何组合列表和代码块。
我有一个 SQLite3 数据库,其中包含以下(的相关部分).schema:
CREATE TABLE users (id INTEGER PRIMARY KEY NOT NULL, user TEXT UNIQUE);
CREATE TABLE locations (id INTEGER PRIMARY KEY NOT NULL, name TEXT UNIQUE);
CREATE TABLE purchases (location_id INTEGER, user_id INTEGER);
CREATE TABLE sales (location_id integer, user_id INTEGER);
purchases
有大约 450 万个条目,users
大约 300k,sales
大约 100k,locations
大约 250 - 只是为了衡量数据量。
我想要的用途是生成一个 JSON object 以传递给另一个应用程序,通过执行以下操作在数量上非常压缩:
-通过 location_id、user_id 将购买和销售分组为一个共同的 table - IOW,获取每个用户每个位置的 "actions" 数量。我能做到,结果类似于
loc | usid | loccount
-----------------------
1 | 1246 | 123
1 | 2345 | 1
13 | 1246 | 46
13 | 8732 | 4
27 | 2345 | 41
(至少看起来不错,这样的体积总是很难分辨;查询:
select location_id,user_id,count(location_id) from
(select location_id,user_id from purchases
union all
select location_id,user_id from sales)
group by location_id,user_id order by user_id`
)
-然后,转置那个巨人 table 这样我会得到:
usid | loc1 | loc13 | loc27
---------------------------
1246 | 123 | 46 | 0
2345 | 1 | 0 | 41
8732 | 0 | 4 | 0
我做不到,这是我对这个问题的绝对关键点。我尝试了一些我在网上找到的东西,尤其是在这里,但我刚刚开始使用 SQLite 并且不了解很多查询。
-最后,将table翻译成纯文本,以便写入JSON:
user | AAAA | BBBBB | CCCCC
---------------------------
zeta | 123 | 46 | 0
beta | 1 | 0 | 41
iota | 0 | 4 | 0
我 可能 可以做很多实验和内部连接,尽管我总是不确定处理此类数据量的最佳方法是什么,因此我不介意一个指针。
整个事情都写在Python的sqlite3接口中,如果重要的话。最后,我希望有一些东西我可以为每个用户做一个 "for" 循环以生成 JSON,这当然会非常简单。如果查询需要很长时间(<10 分钟就好了)也没关系,它只是每天 运行 两次作为一种备份。我只有一个很小的 VPS 可用,但仅限于单核,性能与我相当强大的台式机一样好。 (i5-3570k 运行宁 Debian。)
table headers 只是示例,因为我不太确定我是否可以为它们使用整数(如果可以,我没有发现语法),只要我是以某种方式能够在 table 位置查找数字部分我很好。将用户 ID 转换为名称也是如此。列数是事先已知的——它们毕竟只是 INTEGER PRIMARY KEY,我从其他操作中得到了 list()
个。行数可以相当快地确定,大约 3 秒,如果需要的话。
考虑使用子查询来实现您想要的转置输出:
SELECT DISTINCT m.usid,
IFNULL((SELECT t1.loccount FROM tablename t1
WHERE t1.usid = m.usid AND t1.loc=1),0) AS Loc1,
IFNULL((SELECT t2.loccount FROM tablename t2
WHERE t2.usid = m.usid AND t2.loc=13),0) AS Loc13,
IFNULL((SELECT t3.loccount FROM tablename t3
WHERE t3.usid = m.usid AND t3.loc=27),0) AS Loc27
FROM tablename As m
或者,您可以使用嵌套的 IF
语句(或者在使用 CASE/WHEN
的 SQLite 的情况下)派生 table:
SELECT temp.usid, Max(temp.loc1) As Loc1,
Max(temp.loc13) As Loc13, Max(temp.loc27) As Loc27
FROM
(SELECT tablename.usid,
CASE WHEN loc=1 THEN loccount ELSE 0 As Loc1 END,
CASE WHEN loc=13 THEN loccount ELSE 0 As Loc13 END,
CASE WHEN loc=27 THEN loccount ELSE 0 As Loc27 END
FROM tablename) AS temp
GROUP BY temp.usid