可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I don't think that I can use ORDER BY
clause inside the GROUP_CONCAT
function.
Does anyone know a tricky way to accomplish this behavior in SQLite
?
I saw this question before. But I have a complex query .
My statement looks like this:
SELECT
c.col1, c.col3, m.col3, m.col4,
count(m.col1), count(re.col2) AS cnt,
GROUP_CONCAT(p.col1 ORDER BY p.col1) AS "Group1",
GROUP_CONCAT(p.col2 ORDER BY p.col1) AS "Group2",
GROUP_CONCAT(CASE WHEN con.col3 is null THEN p.col1 ELSE con.col3 END),
con.col4, con.col5, p.col3
FROM t1 re
INNER JOIN t2 c ON (re.col1 = c.col1)
INNER JOIN t3 p ON (re.col2 = p.col1)
LEFT JOIN t4 con ON (con.col1 = p.col2)
INNER JOIN t5 m ON (m.col1 = c.col5)
GROUP BY re.col1
Group1
and Group2
is coming from the same table but different columns: I want to preserve the order of the Group1
with Group2
:
table t3
+------+------+
| col1 | col2 |
+------+------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
| 5 | E |
+------+------+
so if Group1
appears like this 2,1,3
Group2
should appear like this B,A,C
回答1:
SQLite doesn't support ORDER BY
inside a GROUP_CONCAT
, but you can actually fake it:
GROUP_CONCAT(list_order || ':' || value)
Then you need to split the result in code in order to get back your sort and value.
回答2:
What about something like this?
SELECT
col1, col3, col3, col4,
count(col1), count(re.col2) AS cnt,
GROUP_CONCAT(p.col1) AS "Group1",
GROUP_CONCAT(p.col2) AS "Group2",
GROUP_CONCAT(CASE WHEN con.col3 is null THEN p.col1 ELSE con.col3 END),
con.col4, con.col5, p.col3
FROM (
SELECT
*
FROM t1 re
INNER JOIN t2 c ON (re.col1 = c.col1)
INNER JOIN t3 p ON (re.col2 = p.col1)
LEFT JOIN t4 con ON (con.col1 = p.col2)
INNER JOIN t5 m ON (m.col1 = c.col5)
ORDER BY
p.col1 ASC,
p.col2 ASC
)
GROUP BY re.col1
I Haven't tested it but if you can share some data...
回答3:
To avoid any indeterminism you can use recursive CTE like this:
sqlite> create table t3(pos,col1,col2);
sqlite> insert into t3 values(1,2,'B'),(2,1,'A'),(3,5,'E');
sqlite> select * from t3;
1|2|B
2|1|A
3|5|E
sqlite>
with
sorted(pos,c1,c2) as (
select row_number() over (order by t3.pos), -- sorting by first column's value
t3.col1, t3.col2
from t3
),
concat(pos,c1,c2) as (
select sorted.pos,sorted.c1,sorted.c2 -- starting with values for first position
from sorted
where sorted.pos=1
union all
select sorted.pos,
concat.c1||','||sorted.c1, -- adding next value from col1
concat.c2||','||sorted.c2 -- adding next value from col2
from concat
join sorted
on concat.pos+1 = sorted.pos -- going through subsequent positions
)
select c1, c2
from concat
order by pos desc
limit 1; -- order by desc limit 1 means 'take the row with largest number'
2,1,5|B,A,E
Although quite elaborate, this solution guarantees proper sorting and can easily be extended with more columns. The ordering column can have gaps - the sorted
CTE takes care of making it into a proper integer sequence.
Note that row_number() over (order by...)
may require a decently recent version of sqlite which supports windowing functions.
回答4:
I have tried this and it make the work
SELECT
c.col1, c.col3, m.col3, m.col4,
count(m.col1), count(re.col2) AS cnt,
GROUP_CONCAT(p.col1 ORDER BY p.col1) AS "Group1",
GROUP_CONCAT(p.col2 ORDER BY p.col1) AS "Group2",
GROUP_CONCAT(CASE WHEN con.col3 is null THEN p.col1 ELSE con.col3 END),
con.col4, con.col5, p.col3
FROM t1 re
INNER JOIN t2 c ON (re.col1 = c.col1)
INNER JOIN (
SELECT col1, col2, col3, col4, col5 FROM t3 ORDER BY col1
) AS p ON (re.col2 = p.col1)
LEFT JOIN t4 con ON (con.col1 = p.col2)
INNER JOIN t5 m ON (m.col1 = c.col5)
GROUP BY re.col1